Ugochukwu Mmaduekwe 2 недель назад
Родитель
Сommit
160bf1ecb2
100 измененных файлов с 3157 добавлено и 1900 удалено
  1. 7 0
      CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr
  2. 2 0
      CryptoLib.Tests/src/Asn1/Asn1SequenceParserTests.pas
  3. 1 1
      CryptoLib.Tests/src/Asn1/EnumeratedTests.pas
  4. 1 1
      CryptoLib.Tests/src/Asn1/EqualsAndHashCodeTests.pas
  5. 1 0
      CryptoLib.Tests/src/Asn1/GeneralizedTimeTests.pas
  6. 1 1
      CryptoLib.Tests/src/Asn1/InputStreamTests.pas
  7. 0 1
      CryptoLib.Tests/src/Asn1/OIDTests.pas
  8. 2 2
      CryptoLib.Tests/src/Asn1/OctetStringTests.pas
  9. 0 1
      CryptoLib.Tests/src/Asn1/PKCS/Pkcs10CertRequestTests.pas
  10. 2 3
      CryptoLib.Tests/src/Asn1/ParseTests.pas
  11. 2 4
      CryptoLib.Tests/src/Asn1/ParsingTests.pas
  12. 0 1
      CryptoLib.Tests/src/Asn1/PrivateKeyInfoTests.pas
  13. 0 1
      CryptoLib.Tests/src/Asn1/RelativeOidTests.pas
  14. 2 1
      CryptoLib.Tests/src/Asn1/SetTests.pas
  15. 1 1
      CryptoLib.Tests/src/Asn1/TagTests.pas
  16. 1 2
      CryptoLib.Tests/src/Asn1/UtcTimeTests.pas
  17. 1 1
      CryptoLib.Tests/src/Asn1/X509/CertificateTests.pas
  18. 0 2
      CryptoLib.Tests/src/Asn1/X509/DeltaCertificateTests.pas
  19. 0 1
      CryptoLib.Tests/src/Asn1/X509/GeneralNameTests.pas
  20. 0 1
      CryptoLib.Tests/src/Asn1/X509/KeyUsageTests.pas
  21. 0 1
      CryptoLib.Tests/src/Asn1/X509/SubjectKeyIdentifierTests.pas
  22. 0 1
      CryptoLib.Tests/src/Asn1/X509/X509AltTests.pas
  23. 2 1
      CryptoLib.Tests/src/Asn1/X509/X509ExtensionsTests.pas
  24. 0 3
      CryptoLib.Tests/src/Asn1/X509/X509NameTests.pas
  25. 0 1
      CryptoLib.Tests/src/Crypto/DigestRandomNumberTests.pas
  26. 0 1
      CryptoLib.Tests/src/Crypto/ISO9796Tests.pas
  27. 0 1
      CryptoLib.Tests/src/Crypto/PssTests.pas
  28. 0 1
      CryptoLib.Tests/src/Crypto/RSABlindedTests.pas
  29. 0 1
      CryptoLib.Tests/src/Crypto/RSADigestSignerTests.pas
  30. 0 2
      CryptoLib.Tests/src/Crypto/RSATests.pas
  31. 1 2
      CryptoLib.Tests/src/Crypto/X931SignerTests.pas
  32. 0 1
      CryptoLib.Tests/src/Math/BigIntegerTests.pas
  33. 0 1
      CryptoLib.Tests/src/Math/ECAlgorithmsTests.pas
  34. 0 1
      CryptoLib.Tests/src/Math/ECPointTests.pas
  35. 0 1
      CryptoLib.Tests/src/Math/PascalCoinECIESTests.pas
  36. 0 1
      CryptoLib.Tests/src/Others/ECTests.pas
  37. 0 1
      CryptoLib.Tests/src/Others/NamedCurveTests.pas
  38. 0 1
      CryptoLib.Tests/src/Others/SignerUtilitiesTests.pas
  39. 0 1
      CryptoLib.Tests/src/Security/SecureRandomTests.pas
  40. 1 2
      CryptoLib.Tests/src/Utils/ClpIShortenedDigest.pas
  41. 0 3
      CryptoLib.Tests/src/Utils/Pem/PemReaderTests.pas
  42. 730 0
      CryptoLib/src/Asn1/ClpAsn1Core.pas
  43. 1 1
      CryptoLib/src/Asn1/ClpAsn1Dumper.pas
  44. 746 0
      CryptoLib/src/Asn1/ClpAsn1Encodings.pas
  45. 87 1764
      CryptoLib/src/Asn1/ClpAsn1Objects.pas
  46. 1298 0
      CryptoLib/src/Asn1/ClpAsn1Parsers.pas
  47. 8 1
      CryptoLib/src/Asn1/ClpAsn1Streams.pas
  48. 84 0
      CryptoLib/src/Asn1/ClpAsn1Tags.pas
  49. 3 0
      CryptoLib/src/Asn1/ClpAsn1Utilities.pas
  50. 0 1
      CryptoLib/src/Asn1/Eac/ClpEacObjectIdentifiers.pas
  51. 3 1
      CryptoLib/src/Asn1/Pkcs/ClpPkcsAsn1Objects.pas
  52. 2 0
      CryptoLib/src/Asn1/Sec/ClpSecAsn1Objects.pas
  53. 3 3
      CryptoLib/src/Asn1/X500/Style/ClpIetfUtilities.pas
  54. 2 0
      CryptoLib/src/Asn1/X509/ClpAlgorithmIdentifier.pas
  55. 2 0
      CryptoLib/src/Asn1/X509/ClpDigestInfo.pas
  56. 2 0
      CryptoLib/src/Asn1/X509/ClpDsaParameter.pas
  57. 0 1
      CryptoLib/src/Asn1/X509/ClpRfc5280Asn1Utilities.pas
  58. 2 0
      CryptoLib/src/Asn1/X509/ClpV2AttributeCertificateInfoGenerator.pas
  59. 2 0
      CryptoLib/src/Asn1/X509/ClpV3TbsCertificateGenerator.pas
  60. 3 2
      CryptoLib/src/Asn1/X509/ClpX509Asn1Objects.pas
  61. 1 2
      CryptoLib/src/Asn1/X509/ClpX509DefaultEntryConverter.pas
  62. 1 0
      CryptoLib/src/Asn1/X509/ClpX509Extension.pas
  63. 1 1
      CryptoLib/src/Asn1/X509/ClpX509ExtensionUtilities.pas
  64. 2 0
      CryptoLib/src/Asn1/X509/ClpX509ExtensionsGenerator.pas
  65. 1 0
      CryptoLib/src/Asn1/X509/ClpX509NameEntryConverter.pas
  66. 1 0
      CryptoLib/src/Asn1/X509/ClpX509SignatureUtilities.pas
  67. 2 0
      CryptoLib/src/Asn1/X9/ClpDHDomainParameters.pas
  68. 2 1
      CryptoLib/src/Asn1/X9/ClpDHValidationParams.pas
  69. 2 4
      CryptoLib/src/Asn1/X9/ClpX9Asn1Objects.pas
  70. 2 0
      CryptoLib/src/Asn1/X9/ClpX9ECC.pas
  71. 2 0
      CryptoLib/src/Asn1/X9/ClpX9ECParameters.pas
  72. 0 1
      CryptoLib/src/Crypto/Ciphers/ClpIESCipher.pas
  73. 1 2
      CryptoLib/src/Crypto/Encodings/ClpOaepEncoding.pas
  74. 0 1
      CryptoLib/src/Crypto/Engines/ClpRsaEngine.pas
  75. 0 1
      CryptoLib/src/Crypto/Generators/ClpRsaKeyPairGenerator.pas
  76. 1 2
      CryptoLib/src/Crypto/Macs/ClpMacUtilities.pas
  77. 1 2
      CryptoLib/src/Crypto/Operators/ClpAsn1DigestFactory.pas
  78. 0 1
      CryptoLib/src/Crypto/Operators/ClpAsn1SignatureFactory.pas
  79. 0 1
      CryptoLib/src/Crypto/Operators/ClpAsn1VerifierFactory.pas
  80. 0 1
      CryptoLib/src/Crypto/Operators/ClpAsn1VerifierFactoryProvider.pas
  81. 1 3
      CryptoLib/src/Crypto/Parameters/ClpECDomainParameters.pas
  82. 0 2
      CryptoLib/src/Crypto/Parameters/ClpECKeyParameters.pas
  83. 0 1
      CryptoLib/src/Crypto/Parameters/ClpECPublicKeyParameters.pas
  84. 0 2
      CryptoLib/src/Crypto/Parameters/ClpEd25519PrivateKeyParameters.pas
  85. 0 2
      CryptoLib/src/Crypto/Parameters/ClpEd25519PublicKeyParameters.pas
  86. 1 2
      CryptoLib/src/Crypto/Parameters/ClpParameterUtilities.pas
  87. 0 2
      CryptoLib/src/Crypto/Parameters/ClpX25519PrivateKeyParameters.pas
  88. 0 2
      CryptoLib/src/Crypto/Parameters/ClpX25519PublicKeyParameters.pas
  89. 0 2
      CryptoLib/src/Crypto/Parsers/ClpECIESPublicKeyParser.pas
  90. 1 2
      CryptoLib/src/Crypto/Randoms/ClpSecureRandom.pas
  91. 0 1
      CryptoLib/src/Crypto/Signers/ClpDsaDigestSigner.pas
  92. 0 1
      CryptoLib/src/Crypto/Signers/ClpECDsaSigner.pas
  93. 0 4
      CryptoLib/src/Crypto/Signers/ClpRsaDigestSigner.pas
  94. 1 6
      CryptoLib/src/Crypto/Signers/ClpSignerUtilities.pas
  95. 1 0
      CryptoLib/src/Crypto/Signers/SignerEncodings/ClpSignersEncodings.pas
  96. 1 10
      CryptoLib/src/Factories/ClpPrivateKeyFactory.pas
  97. 0 8
      CryptoLib/src/Factories/ClpPublicKeyFactory.pas
  98. 1 2
      CryptoLib/src/GeneralUtilities/ClpCryptoLibComparers.pas
  99. 0 1
      CryptoLib/src/GeneralUtilities/ClpEnumUtilities.pas
  100. 124 0
      CryptoLib/src/Interfaces/Asn1/ClpIAsn1Core.pas

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

@@ -508,6 +508,13 @@ uses
   ClpOSRandomProvider in '..\..\CryptoLib\src\Rngs\Providers\ClpOSRandomProvider.pas',
   ClpIRandomNumberGenerator in '..\..\CryptoLib\src\Interfaces\Rngs\ClpIRandomNumberGenerator.pas',
   ClpAesRandomProvider in '..\..\CryptoLib\src\Rngs\Providers\ClpAesRandomProvider.pas',
+  ClpAsn1Parsers in '..\..\CryptoLib\src\Asn1\ClpAsn1Parsers.pas',
+  ClpAsn1Core in '..\..\CryptoLib\src\Asn1\ClpAsn1Core.pas',
+  ClpIAsn1Parsers in '..\..\CryptoLib\src\Interfaces\Asn1\ClpIAsn1Parsers.pas',
+  ClpIAsn1Core in '..\..\CryptoLib\src\Interfaces\Asn1\ClpIAsn1Core.pas',
+  ClpAsn1Tags in '..\..\CryptoLib\src\Asn1\ClpAsn1Tags.pas',
+  ClpIAsn1Encodings in '..\..\CryptoLib\src\Interfaces\Asn1\ClpIAsn1Encodings.pas',
+  ClpAsn1Encodings in '..\..\CryptoLib\src\Asn1\ClpAsn1Encodings.pas',
   ClpFixedSecureRandom in '..\src\Utils\ClpFixedSecureRandom.pas',
   ClpIFixedSecureRandom in '..\src\Utils\ClpIFixedSecureRandom.pas',
   ClpIShortenedDigest in '..\src\Utils\ClpIShortenedDigest.pas',

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

@@ -35,6 +35,8 @@ uses
   ClpBigInteger,
   ClpAsn1Objects,
   ClpIAsn1Objects,
+  ClpIAsn1Parsers,
+  ClpAsn1Parsers,
   ClpCryptoLibTypes,
   CryptoLibTestBase;
 

+ 1 - 1
CryptoLib.Tests/src/Asn1/EnumeratedTests.pas

@@ -33,7 +33,7 @@ uses
 {$ENDIF FPC}
   ClpAsn1Objects,
   ClpIAsn1Objects,
-  ClpEncoders,
+  ClpIAsn1Core,
   ClpCryptoLibTypes,
   CryptoLibTestBase;
 

+ 1 - 1
CryptoLib.Tests/src/Asn1/EqualsAndHashCodeTests.pas

@@ -34,10 +34,10 @@ uses
 {$ENDIF FPC}
   ClpAsn1Objects,
   ClpIAsn1Objects,
+  ClpIAsn1Core,
   ClpAsn1Streams,
   ClpConverters,
   ClpCryptoLibTypes,
-  ClpDateTimeUtilities,
   CryptoLibTestBase;
 
 type

+ 1 - 0
CryptoLib.Tests/src/Asn1/GeneralizedTimeTests.pas

@@ -34,6 +34,7 @@ uses
 {$ENDIF FPC}
   ClpAsn1Objects,
   ClpIAsn1Objects,
+  ClpAsn1Core,
   ClpDateTimeUtilities,
   ClpCryptoLibTypes,
   CryptoLibTestBase;

+ 1 - 1
CryptoLib.Tests/src/Asn1/InputStreamTests.pas

@@ -24,7 +24,6 @@ interface
 {$ENDIF FPC}
 
 uses
-  Classes,
   SysUtils,
 {$IFDEF FPC}
   fpcunit,
@@ -34,6 +33,7 @@ uses
 {$ENDIF FPC}
   ClpAsn1Objects,
   ClpIAsn1Objects,
+  ClpIAsn1Core,
   ClpAsn1Streams,
   ClpEncoders,
   ClpCryptoLibTypes,

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

@@ -24,7 +24,6 @@ interface
 {$ENDIF FPC}
 
 uses
-  Classes,
   SysUtils,
 {$IFDEF FPC}
   fpcunit,

+ 2 - 2
CryptoLib.Tests/src/Asn1/OctetStringTests.pas

@@ -25,7 +25,6 @@ interface
 
 uses
   Classes,
-  SysUtils,
 {$IFDEF FPC}
   fpcunit,
   testregistry,
@@ -34,7 +33,8 @@ uses
 {$ENDIF FPC}
   ClpAsn1Objects,
   ClpIAsn1Objects,
-  ClpStreams,
+  ClpIAsn1Parsers,
+  ClpAsn1Parsers,
   ClpStreamUtilities,
   ClpCryptoLibTypes,
   CryptoLibTestBase;

+ 0 - 1
CryptoLib.Tests/src/Asn1/PKCS/Pkcs10CertRequestTests.pas

@@ -33,7 +33,6 @@ uses
 {$ENDIF FPC}
   ClpPkcsAsn1Objects,
   ClpIPkcsAsn1Objects,
-  ClpArrayUtilities,
   ClpCryptoLibTypes,
   CryptoLibTestBase;
 

+ 2 - 3
CryptoLib.Tests/src/Asn1/ParseTests.pas

@@ -24,7 +24,6 @@ interface
 {$ENDIF FPC}
 
 uses
-  Classes,
   SysUtils,
 {$IFDEF FPC}
   fpcunit,
@@ -32,8 +31,8 @@ uses
 {$ELSE}
   TestFramework,
 {$ENDIF FPC}
-  ClpAsn1Objects,
-  ClpIAsn1Objects,
+  ClpAsn1Parsers,
+  ClpIAsn1Parsers,
   ClpEncoders,
   ClpCryptoLibTypes,
   CryptoLibTestBase;

+ 2 - 4
CryptoLib.Tests/src/Asn1/ParsingTests.pas

@@ -24,16 +24,14 @@ interface
 {$ENDIF FPC}
 
 uses
-  Classes,
-  SysUtils,
 {$IFDEF FPC}
   fpcunit,
   testregistry,
 {$ELSE}
   TestFramework,
 {$ENDIF FPC}
-  ClpAsn1Objects,
-  ClpIAsn1Objects,
+  ClpIAsn1Parsers,
+  ClpAsn1Parsers,
   ClpCryptoLibTypes,
   CryptoLibTestBase;
 

+ 0 - 1
CryptoLib.Tests/src/Asn1/PrivateKeyInfoTests.pas

@@ -34,7 +34,6 @@ uses
   ClpIAsn1Objects,
   ClpPkcsAsn1Objects,
   ClpIPkcsAsn1Objects,
-  ClpArrayUtilities,
   ClpCryptoLibTypes,
   CryptoLibTestBase;
 

+ 0 - 1
CryptoLib.Tests/src/Asn1/RelativeOidTests.pas

@@ -24,7 +24,6 @@ interface
 {$ENDIF FPC}
 
 uses
-  Classes,
   SysUtils,
 {$IFDEF FPC}
   fpcunit,

+ 2 - 1
CryptoLib.Tests/src/Asn1/SetTests.pas

@@ -24,7 +24,6 @@ interface
 {$ENDIF FPC}
 
 uses
-  Classes,
   SysUtils,
 {$IFDEF FPC}
   fpcunit,
@@ -34,6 +33,8 @@ uses
 {$ENDIF FPC}
   ClpAsn1Objects,
   ClpIAsn1Objects,
+  ClpAsn1Core,
+  ClpIAsn1Core,
   ClpCryptoLibTypes,
   CryptoLibTestBase;
 

+ 1 - 1
CryptoLib.Tests/src/Asn1/TagTests.pas

@@ -24,7 +24,6 @@ interface
 {$ENDIF FPC}
 
 uses
-  Classes,
   SysUtils,
 {$IFDEF FPC}
   fpcunit,
@@ -35,6 +34,7 @@ uses
   ClpAsn1Objects,
   ClpIAsn1Objects,
   ClpAsn1Streams,
+  ClpAsn1Tags,
   ClpSecureRandom,
   ClpISecureRandom,
   ClpBitUtilities,

+ 1 - 2
CryptoLib.Tests/src/Asn1/UtcTimeTests.pas

@@ -23,7 +23,6 @@ interface
 
 uses
   SysUtils,
-  DateUtils,
 {$IFDEF FPC}
   fpcunit,
   testregistry,
@@ -33,7 +32,7 @@ uses
   ClpAsn1Objects,
   ClpIAsn1Objects,
   ClpDateTimeUtilities,
-  ClpCryptoLibTypes,
+
   CryptoLibTestBase;
 
 type

+ 1 - 1
CryptoLib.Tests/src/Asn1/X509/CertificateTests.pas

@@ -35,8 +35,8 @@ uses
   ClpIX509Asn1Objects,
   ClpAsn1Objects,
   ClpIAsn1Objects,
+  ClpIAsn1Core,
   ClpIX509Extension,
-  ClpEncoders,
   ClpCryptoLibTypes,
   CryptoLibTestBase;
 

+ 0 - 2
CryptoLib.Tests/src/Asn1/X509/DeltaCertificateTests.pas

@@ -45,12 +45,10 @@ uses
   ClpCryptoLibTypes,
   ClpBigInteger,
   ClpGeneratorUtilities,
-  ClpRsaKeyPairGenerator,
   ClpRsaKeyGenerationParameters,
   ClpIRsaKeyGenerationParameters,
   ClpSecureRandom,
   ClpISecureRandom,
-  ClpECKeyPairGenerator,
   ClpECKeyGenerationParameters,
   ClpSecObjectIdentifiers,
   ClpCustomNamedCurves,

+ 0 - 1
CryptoLib.Tests/src/Asn1/X509/GeneralNameTests.pas

@@ -33,7 +33,6 @@ uses
 {$ENDIF FPC}
   ClpX509Asn1Objects,
   ClpIX509Asn1Objects,
-  ClpArrayUtilities,
   ClpCryptoLibTypes,
   CryptoLibTestBase;
 

+ 0 - 1
CryptoLib.Tests/src/Asn1/X509/KeyUsageTests.pas

@@ -32,7 +32,6 @@ uses
   TestFramework,
 {$ENDIF FPC}
   ClpX509Asn1Objects,
-  ClpIX509Asn1Objects,
   CryptoLibTestBase;
 
 type

+ 0 - 1
CryptoLib.Tests/src/Asn1/X509/SubjectKeyIdentifierTests.pas

@@ -34,7 +34,6 @@ uses
   ClpX509Asn1Objects,
   ClpIX509Asn1Objects,
   ClpX509ExtensionUtilities,
-  ClpArrayUtilities,
   ClpCryptoLibTypes,
   CryptoLibTestBase;
 

+ 0 - 1
CryptoLib.Tests/src/Asn1/X509/X509AltTests.pas

@@ -38,7 +38,6 @@ uses
   ClpPkcsObjectIdentifiers,
   ClpAsn1Objects,
   ClpIAsn1Objects,
-  ClpArrayUtilities,
   ClpCryptoLibTypes,
   CryptoLibTestBase;
 

+ 2 - 1
CryptoLib.Tests/src/Asn1/X509/X509ExtensionsTests.pas

@@ -38,7 +38,8 @@ uses
   ClpIX509Extension,
   ClpAsn1Objects,
   ClpIAsn1Objects,
-  ClpArrayUtilities,
+  ClpAsn1Core,
+  ClpIAsn1Core,
   ClpCryptoLibTypes,
   CryptoLibTestBase;
 

+ 0 - 3
CryptoLib.Tests/src/Asn1/X509/X509NameTests.pas

@@ -34,9 +34,6 @@ uses
 {$ENDIF FPC}
   ClpX509Asn1Objects,
   ClpIX509Asn1Objects,
-  ClpAsn1Objects,
-  ClpIAsn1Objects,
-  ClpArrayUtilities,
   ClpCryptoLibTypes,
   CryptoLibTestBase;
 

+ 0 - 1
CryptoLib.Tests/src/Crypto/DigestRandomNumberTests.pas

@@ -24,7 +24,6 @@ interface
 {$ENDIF FPC}
 
 uses
-  Classes,
   SysUtils,
 {$IFDEF FPC}
   fpcunit,

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

@@ -24,7 +24,6 @@ interface
 {$ENDIF FPC}
 
 uses
-  Classes,
   SysUtils,
 {$IFDEF FPC}
   fpcunit,

+ 0 - 1
CryptoLib.Tests/src/Crypto/PssTests.pas

@@ -51,7 +51,6 @@ uses
   ClpIAsymmetricCipherKeyPair,
   ClpISigner,
   ClpSignerUtilities,
-  ClpGeneratorUtilities,
   ClpISecureRandom,
   ClpSecureRandom,
   ClpConverters,

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

@@ -8,7 +8,6 @@ interface
 
 uses
   SysUtils,
-  Classes,
 {$IFDEF FPC}
   fpcunit,
   testregistry,

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

@@ -25,7 +25,6 @@ interface
 
 uses
   SysUtils,
-  Classes,
 {$IFDEF FPC}
   fpcunit,
   testregistry,

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

@@ -48,8 +48,6 @@ uses
   ClpIAsymmetricKeyParameter,
   ClpISigner,
   ClpSignerUtilities,
-  ClpDigestUtilities,
-  ClpGeneratorUtilities,
   ClpISecureRandom,
   ClpSecureRandom,
   ClpConverters,

+ 1 - 2
CryptoLib.Tests/src/Crypto/X931SignerTests.pas

@@ -24,7 +24,7 @@ interface
 {$ENDIF FPC}
 
 uses
-  SysUtils,
+
 {$IFDEF FPC}
   fpcunit,
   testregistry,
@@ -40,7 +40,6 @@ uses
   ClpIRsaEngine,
   ClpX931Signer,
   ClpDigestUtilities,
-  ClpIDigest,
   ClpISigner,
   ClpEncoders,
   ClpArrayUtilities,

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

@@ -24,7 +24,6 @@ interface
 {$ENDIF FPC}
 
 uses
-  Classes,
   Math,
   SysUtils,
 {$IFDEF FPC}

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

@@ -27,7 +27,6 @@ interface
 {$ENDIF FPC}
 
 uses
-  Classes,
   SysUtils,
 {$IFDEF FPC}
   fpcunit,

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

@@ -24,7 +24,6 @@ interface
 {$ENDIF FPC}
 
 uses
-  Classes,
   SysUtils,
   Math,
 {$IFDEF FPC}

+ 0 - 1
CryptoLib.Tests/src/Math/PascalCoinECIESTests.pas

@@ -15,7 +15,6 @@ uses
 {$ELSE}
   TestFramework,
 {$ENDIF FPC}
-  ClpECC,
   ClpIECC,
   ClpIESEngine,
   ClpIIESCipher,

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

@@ -24,7 +24,6 @@ interface
 {$ENDIF FPC}
 
 uses
-  Classes,
   SysUtils,
 {$IFDEF FPC}
   fpcunit,

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

@@ -24,7 +24,6 @@ interface
 {$ENDIF FPC}
 
 uses
-  Classes,
   SysUtils,
 {$IFDEF FPC}
   fpcunit,

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

@@ -24,7 +24,6 @@ interface
 {$ENDIF FPC}
 
 uses
-  Classes,
   SysUtils,
 {$IFDEF FPC}
   fpcunit,

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

@@ -24,7 +24,6 @@ interface
 {$ENDIF FPC}
 
 uses
-  Classes,
   SysUtils,
 {$IFDEF FPC}
   fpcunit,

+ 1 - 2
CryptoLib.Tests/src/Utils/ClpIShortenedDigest.pas

@@ -24,8 +24,7 @@ interface
 {$ENDIF FPC}
 
 uses
-  ClpIDigest,
-  ClpCryptoLibTypes;
+  ClpIDigest;
 
 type
 

+ 0 - 3
CryptoLib.Tests/src/Utils/Pem/PemReaderTests.pas

@@ -35,13 +35,10 @@ uses
   ClpPemObjects,
   ClpIPemObjects,
   ClpAsn1Objects,
-  ClpIAsn1Objects,
   ClpPkcsAsn1Objects,
   ClpIPkcsAsn1Objects,
   ClpX509Asn1Objects,
   ClpIX509Asn1Objects,
-  ClpConverters,
-  ClpEncoders,
   ClpCryptoLibTypes,
   CryptoLibTestBase;
 

+ 730 - 0
CryptoLib/src/Asn1/ClpAsn1Core.pas

@@ -0,0 +1,730 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpAsn1Core;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  Math,
+  ClpStreams,
+  ClpCryptoLibTypes,
+  ClpIAsn1Core,
+  ClpIAsn1Objects,
+  ClpIAsn1Encodings,
+  ClpAsn1Streams;
+
+type
+  /// <summary>
+  /// Abstract base class for ASN.1 encodable objects.
+  /// </summary>
+  TAsn1Encodable = class abstract(TInterfacedObject, IAsn1Encodable, IAsn1Convertible)
+  public
+    const
+      Ber = 'BER';
+      Der = 'DER';
+      DL = 'DL';
+
+  public
+    /// <summary>
+    /// Encode this object to a stream using BER encoding.
+    /// </summary>
+    procedure EncodeTo(const AOutput: TStream); overload; virtual;
+    /// <summary>
+    /// Encode this object to a stream using the specified encoding.
+    /// </summary>
+    procedure EncodeTo(const AOutput: TStream; const AEncoding: String); overload; virtual;
+    /// <summary>
+    /// Get the encoded representation of this object.
+    /// </summary>
+    function GetEncoded(): TCryptoLibByteArray; overload;
+    function GetEncoded(const AEncoding: String): TCryptoLibByteArray; overload;
+    function GetEncoded(const AEncoding: String; APreAlloc, APostAlloc: Int32): TCryptoLibByteArray; overload; virtual;
+    /// <summary>
+    /// Get the DER encoding of the object, nil if the DER encoding cannot be made.
+    /// </summary>
+    function GetDerEncoded(): TCryptoLibByteArray;
+    /// <summary>
+    /// Check if this object equals another.
+    /// </summary>
+    function Equals(const AObj: IAsn1Convertible): Boolean; reintroduce; overload;
+    /// <summary>
+    /// Get the hash code for this object.
+    /// </summary>
+    function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt; {$ENDIF DELPHI} override;
+    /// <summary>
+    /// Convert this object to an ASN.1 object.
+    /// </summary>
+    function ToAsn1Object(): IAsn1Object; virtual; abstract;
+  end;
+
+  /// <summary>
+  /// Vector for ASN.1 encodable objects.
+  /// </summary>
+  TAsn1EncodableVector = class(TInterfacedObject, IAsn1EncodableVector)
+  strict private
+    const
+      DefaultCapacity = 10;
+
+    class var
+      FEmptyElements: TCryptoLibGenericArray<IAsn1Encodable>;
+  
+  public
+    class property EmptyElements: TCryptoLibGenericArray<IAsn1Encodable> read FEmptyElements;
+
+  strict private
+    FElements: TCryptoLibGenericArray<IAsn1Encodable>;
+    FElementCount: Int32;
+    FCopyOnWrite: Boolean;
+
+    function PrepareCapacity(ARequiredCapacity: Int32): Int32;
+    procedure Reallocate(AMinCapacity: Int32);
+    class function CopyElements(const AElements: TCryptoLibGenericArray<IAsn1Encodable>;
+      AElementCount: Int32): TCryptoLibGenericArray<IAsn1Encodable>; overload; static;
+
+  public
+    /// <summary>
+    /// Create an empty vector with default capacity.
+    /// </summary>
+    constructor Create(); overload;
+    /// <summary>
+    /// Create an empty vector with specified initial capacity.
+    /// </summary>
+    constructor Create(AInitialCapacity: Int32); overload;
+    /// <summary>
+    /// Create a vector with a single element.
+    /// </summary>
+    constructor Create(const AElement: IAsn1Encodable); overload;
+    /// <summary>
+    /// Create a vector with two elements.
+    /// </summary>
+    constructor Create(const AElement1, AElement2: IAsn1Encodable); overload;
+    /// <summary>
+    /// Create a vector with multiple elements.
+    /// </summary>
+    constructor Create(const AElements: array of IAsn1Encodable); overload;
+
+    /// <summary>
+    /// Add an element to the vector.
+    /// </summary>
+    procedure Add(const AElement: IAsn1Encodable); overload;
+    /// <summary>
+    /// Add two elements to the vector.
+    /// </summary>
+    procedure Add(const AElement1, AElement2: IAsn1Encodable); overload;
+    /// <summary>
+    /// Add multiple elements to the vector.
+    /// </summary>
+    procedure Add(const AObjs: array of IAsn1Encodable); overload;
+    /// <summary>
+    /// Add an optional element (if not nil).
+    /// </summary>
+    procedure AddOptional(const AElement: IAsn1Encodable); overload;
+    /// <summary>
+    /// Add two optional elements.
+    /// </summary>
+    procedure AddOptional(const AElement1, AElement2: IAsn1Encodable); overload;
+    /// <summary>
+    /// Add multiple optional elements.
+    /// </summary>
+    procedure AddOptional(const AElements: array of IAsn1Encodable); overload;
+    /// <summary>
+    /// Add an optional tagged element.
+    /// </summary>
+    procedure AddOptionalTagged(AIsExplicit: Boolean; ATagNo: Int32;
+      const AObj: IAsn1Encodable); overload;
+    /// <summary>
+    /// Add an optional tagged element with tag class.
+    /// </summary>
+    procedure AddOptionalTagged(AIsExplicit: Boolean; ATagClass, ATagNo: Int32;
+      const AObj: IAsn1Encodable); overload;
+    /// <summary>
+    /// Add all elements from an enumerable.
+    /// </summary>
+    procedure AddAll(const AE: TCryptoLibGenericArray<IAsn1Encodable>); overload;
+    /// <summary>
+    /// Add all elements from another vector.
+    /// </summary>
+    procedure AddAll(const AOther: IAsn1EncodableVector); overload;
+
+    /// <summary>
+    /// Get an element by index.
+    /// </summary>
+    function GetItem(AIndex: Int32): IAsn1Encodable;
+    /// <summary>
+    /// Get the number of elements.
+    /// </summary>
+    function GetCount(): Int32;
+    /// <summary>
+    /// Copy all elements to a new array.
+    /// </summary>
+    function CopyElements(): TCryptoLibGenericArray<IAsn1Encodable>; overload;
+    /// <summary>
+    /// Take all elements (may return internal array if count matches capacity).
+    /// </summary>
+    function TakeElements(): TCryptoLibGenericArray<IAsn1Encodable>;
+
+    /// <summary>
+    /// Create a vector from a collection.
+    /// </summary>
+    class function FromCollection(const AC: TCryptoLibGenericArray<IAsn1Encodable>): IAsn1EncodableVector; static;
+    /// <summary>
+    /// Create a vector from a single element.
+    /// </summary>
+    class function FromElement(const AElement: IAsn1Encodable): IAsn1EncodableVector; static;
+    /// <summary>
+    /// Create a vector from an enumerable.
+    /// </summary>
+    class function FromEnumerable(const AE: TCryptoLibGenericArray<IAsn1Encodable>): IAsn1EncodableVector; static;
+    /// <summary>
+    /// Clone elements from an array.
+    /// </summary>
+    class function CloneElements(const AElements: TCryptoLibGenericArray<IAsn1Encodable>): TCryptoLibGenericArray<IAsn1Encodable>; static;
+
+    /// <summary>
+    /// Class constructor to initialize static fields.
+    /// </summary>
+    class constructor Create;
+
+    property Items[AIndex: Int32]: IAsn1Encodable read GetItem; default;
+    property Count: Int32 read GetCount;
+  end;
+
+  /// <summary>
+  /// Abstract base class for ASN.1 objects.
+  /// </summary>
+  TAsn1Object = class abstract(TAsn1Encodable, IAsn1Object)
+  strict protected
+    /// <summary>
+    /// Compare this object with another ASN.1 object.
+    /// </summary>
+    function Asn1Equals(const AAsn1Object: IAsn1Object): Boolean; virtual; abstract;
+    /// <summary>
+    /// Get the hash code for this ASN.1 object.
+    /// </summary>
+    function Asn1GetHashCode(): Int32; virtual; abstract;
+
+  public
+    /// <summary>
+    /// Encode this object to a stream using BER encoding.
+    /// </summary>
+    procedure EncodeTo(const AOutput: TStream); override;
+    /// <summary>
+    /// Encode this object to a stream using the specified encoding.
+    /// </summary>
+    procedure EncodeTo(const AOutput: TStream; const AEncoding: String); override;
+    /// <summary>
+    /// Get the encoded representation of this object.
+    /// </summary>
+    function GetEncoded(const AEncoding: String; APreAlloc, APostAlloc: Int32): TCryptoLibByteArray; override;
+    /// <summary>
+    /// Check if this object equals another.
+    /// </summary>
+    function Equals(const AOther: IAsn1Object): Boolean; reintroduce; overload;
+    /// <summary>
+    /// Create an ASN.1 object from a byte array.
+    /// </summary>
+    class function FromByteArray(const AData: TCryptoLibByteArray): IAsn1Object; static;
+    /// <summary>
+    /// Create an ASN.1 object from a stream.
+    /// </summary>
+    class function FromStream(const AInStr: TStream): IAsn1Object; static;
+    /// <summary>
+    /// Get encoding for the specified encoding type.
+    /// </summary>
+    function GetEncoding(AEncoding: Int32): IAsn1Encoding; virtual; abstract;
+    /// <summary>
+    /// Get encoding for the specified encoding type with implicit tagging.
+    /// </summary>
+    function GetEncodingImplicit(AEncoding, ATagClass, ATagNo: Int32): IAsn1Encoding; virtual; abstract;
+    /// <summary>
+    /// Get DER encoding.
+    /// </summary>
+    function GetEncodingDer(): IDerEncoding; virtual; abstract;
+    /// <summary>
+    /// Get DER encoding with implicit tagging.
+    /// </summary>
+    function GetEncodingDerImplicit(ATagClass, ATagNo: Int32): IDerEncoding; virtual; abstract;
+    /// <summary>
+    /// Convert this object to an ASN.1 object (returns self).
+    /// </summary>
+    function ToAsn1Object(): IAsn1Object; override;
+
+  private
+    /// <summary>
+    /// Create an ASN.1 object from a fixed buffer stream.
+    /// </summary>
+    class function FromBufferStream(const ABufferStream: TFixedBufferStream): IAsn1Object; static;
+
+    /// <summary>
+    /// Call Asn1Equals (internal method).
+    /// </summary>
+    function CallAsn1Equals(const AObj: IAsn1Object): Boolean;
+    /// <summary>
+    /// Call Asn1GetHashCode (internal method).
+    /// </summary>
+    function CallAsn1GetHashCode(): Int32;
+  end;
+
+implementation
+
+uses
+  ClpBitUtilities,
+  ClpAsn1Tags,
+  ClpAsn1Objects; // For TDerTaggedObject in AddOptionalTagged
+
+{ TAsn1Encodable }
+
+procedure TAsn1Encodable.EncodeTo(const AOutput: TStream);
+begin
+  ToAsn1Object().EncodeTo(AOutput);
+end;
+
+procedure TAsn1Encodable.EncodeTo(const AOutput: TStream; const AEncoding: String);
+begin
+  ToAsn1Object().EncodeTo(AOutput, AEncoding);
+end;
+
+function TAsn1Encodable.GetEncoded(): TCryptoLibByteArray;
+begin
+  Result := GetEncoded(Ber, 0, 0);
+end;
+
+function TAsn1Encodable.GetEncoded(const AEncoding: String): TCryptoLibByteArray;
+begin
+  Result := GetEncoded(AEncoding, 0, 0);
+end;
+
+function TAsn1Encodable.GetEncoded(const AEncoding: String; APreAlloc, APostAlloc: Int32): TCryptoLibByteArray;
+begin
+  Result := ToAsn1Object().GetEncoded(AEncoding, APreAlloc, APostAlloc);
+end;
+
+function TAsn1Encodable.GetDerEncoded(): TCryptoLibByteArray;
+begin
+  try
+    Result := GetEncoded(Der);
+  except
+    on E: EIOCryptoLibException do
+      Result := nil;
+  end;
+end;
+
+function TAsn1Encodable.Equals(const AObj: IAsn1Convertible): Boolean;
+var
+  LO1, LO2: IAsn1Object;
+begin
+  if (Self as IAsn1Convertible) = AObj then
+  begin
+    Result := True;
+    Exit;
+  end;
+
+  if AObj = nil then
+  begin
+    Result := False;
+    Exit;
+  end;
+
+  LO1 := ToAsn1Object();
+  LO2 := AObj.ToAsn1Object();
+  Result := (LO1 = LO2) or ((LO2 <> nil) and LO1.CallAsn1Equals(LO2));
+end;
+
+function TAsn1Encodable.GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt; {$ENDIF DELPHI}
+begin
+  Result := ToAsn1Object().CallAsn1GetHashCode();
+end;
+
+{ TAsn1EncodableVector }
+
+class function TAsn1EncodableVector.CopyElements(const AElements: TCryptoLibGenericArray<IAsn1Encodable>;
+  AElementCount: Int32): TCryptoLibGenericArray<IAsn1Encodable>;
+var
+  I: Int32;
+begin
+  if AElementCount < 1 then
+  begin
+    Result := FEmptyElements;
+    Exit;
+  end;
+
+  System.SetLength(Result, AElementCount);
+  for I := 0 to AElementCount - 1 do
+    Result[I] := AElements[I];
+end;
+
+constructor TAsn1EncodableVector.Create();
+begin
+  Create(DefaultCapacity);
+end;
+
+constructor TAsn1EncodableVector.Create(AInitialCapacity: Int32);
+begin
+  inherited Create;
+  if AInitialCapacity < 0 then
+    raise EArgumentCryptoLibException.Create('must not be negative');
+
+  if AInitialCapacity = 0 then
+    FElements := FEmptyElements
+  else
+    System.SetLength(FElements, AInitialCapacity);
+  FElementCount := 0;
+  FCopyOnWrite := False;
+end;
+
+constructor TAsn1EncodableVector.Create(const AElement: IAsn1Encodable);
+begin
+  Create();
+  Add(AElement);
+end;
+
+constructor TAsn1EncodableVector.Create(const AElement1, AElement2: IAsn1Encodable);
+begin
+  Create();
+  Add(AElement1);
+  Add(AElement2);
+end;
+
+constructor TAsn1EncodableVector.Create(const AElements: array of IAsn1Encodable);
+var
+  I: Int32;
+begin
+  Create();
+  for I := 0 to System.Length(AElements) - 1 do
+    Add(AElements[I]);
+end;
+
+procedure TAsn1EncodableVector.Add(const AElement: IAsn1Encodable);
+begin
+  if AElement = nil then
+    raise EArgumentNilCryptoLibException.Create('element');
+
+  PrepareCapacity(1);
+  FElements[FElementCount] := AElement;
+  System.Inc(FElementCount);
+end;
+
+procedure TAsn1EncodableVector.Add(const AElement1, AElement2: IAsn1Encodable);
+begin
+  Add(AElement1);
+  Add(AElement2);
+end;
+
+procedure TAsn1EncodableVector.Add(const AObjs: array of IAsn1Encodable);
+var
+  I: Int32;
+begin
+  for I := 0 to System.Length(AObjs) - 1 do
+    Add(AObjs[I]);
+end;
+
+procedure TAsn1EncodableVector.AddOptional(const AElement: IAsn1Encodable);
+begin
+  if AElement <> nil then
+    Add(AElement);
+end;
+
+procedure TAsn1EncodableVector.AddOptional(const AElement1, AElement2: IAsn1Encodable);
+begin
+  AddOptional(AElement1);
+  AddOptional(AElement2);
+end;
+
+procedure TAsn1EncodableVector.AddOptional(const AElements: array of IAsn1Encodable);
+var
+  I: Int32;
+begin
+  if System.Length(AElements) > 0 then
+  begin
+    for I := 0 to System.Length(AElements) - 1 do
+      AddOptional(AElements[I]);
+  end;
+end;
+
+procedure TAsn1EncodableVector.AddOptionalTagged(AIsExplicit: Boolean; ATagNo: Int32;
+  const AObj: IAsn1Encodable);
+var
+  LExplicitness: Int32;
+begin
+  if AObj <> nil then
+  begin
+    if AIsExplicit then
+      LExplicitness := 1  // DeclaredExplicit
+    else
+      LExplicitness := 2; // DeclaredImplicit
+    Add(TDerTaggedObject.Create(LExplicitness, TAsn1Tags.ContextSpecific, ATagNo, AObj));
+  end;
+end;
+
+procedure TAsn1EncodableVector.AddOptionalTagged(AIsExplicit: Boolean; ATagClass, ATagNo: Int32;
+  const AObj: IAsn1Encodable);
+var
+  LExplicitness: Int32;
+begin
+  if AObj <> nil then
+  begin
+    if AIsExplicit then
+      LExplicitness := 1  // DeclaredExplicit
+    else
+      LExplicitness := 2; // DeclaredImplicit
+    Add(TDerTaggedObject.Create(LExplicitness, ATagClass, ATagNo, AObj));
+  end;
+end;
+
+procedure TAsn1EncodableVector.AddAll(const AE: TCryptoLibGenericArray<IAsn1Encodable>);
+var
+  I: Int32;
+begin
+  if AE = nil then
+    raise EArgumentNilCryptoLibException.Create('e');
+
+  for I := 0 to System.Length(AE) - 1 do
+    Add(AE[I]);
+end;
+
+procedure TAsn1EncodableVector.AddAll(const AOther: IAsn1EncodableVector);
+var
+  I: Int32;
+  LOtherElementCount: Int32;
+begin
+  if AOther = nil then
+    raise EArgumentNilCryptoLibException.Create('other');
+
+  LOtherElementCount := AOther.Count;
+  if LOtherElementCount < 1 then
+    Exit;
+
+  PrepareCapacity(LOtherElementCount);
+  for I := 0 to LOtherElementCount - 1 do
+  begin
+    FElements[FElementCount] := AOther[I];
+    System.Inc(FElementCount);
+  end;
+end;
+
+function TAsn1EncodableVector.GetItem(AIndex: Int32): IAsn1Encodable;
+begin
+  if AIndex >= FElementCount then
+    raise EArgumentOutOfRangeCryptoLibException.CreateFmt('%d >= %d', [AIndex, FElementCount]);
+
+  Result := FElements[AIndex];
+end;
+
+function TAsn1EncodableVector.GetCount(): Int32;
+begin
+  Result := FElementCount;
+end;
+
+function TAsn1EncodableVector.CopyElements(): TCryptoLibGenericArray<IAsn1Encodable>;
+begin
+  Result := CopyElements(FElements, FElementCount);
+end;
+
+function TAsn1EncodableVector.TakeElements(): TCryptoLibGenericArray<IAsn1Encodable>;
+var
+  I: Int32;
+begin
+  if FElementCount = 0 then
+  begin
+    Result := FEmptyElements;
+    Exit;
+  end;
+
+  if System.Length(FElements) = FElementCount then
+  begin
+    FCopyOnWrite := True;
+    Result := FElements;
+    Exit;
+  end;
+
+  System.SetLength(Result, FElementCount);
+
+  for I := 0 to FElementCount - 1 do
+    Result[I] := FElements[I];
+end;
+
+function TAsn1EncodableVector.PrepareCapacity(ARequiredCapacity: Int32): Int32;
+var
+  LCapacity, LMinCapacity: Int32;
+begin
+  LCapacity := System.Length(FElements);
+  LMinCapacity := FElementCount + ARequiredCapacity;
+  if (LMinCapacity > LCapacity) or FCopyOnWrite then
+    Reallocate(LMinCapacity);
+  Result := LMinCapacity;
+end;
+
+procedure TAsn1EncodableVector.Reallocate(AMinCapacity: Int32);
+var
+  I: Int32;
+  LOldCapacity, LNewCapacity: Int32;
+  LCopy: TCryptoLibGenericArray<IAsn1Encodable>;
+begin
+  LOldCapacity := System.Length(FElements);
+  LNewCapacity := Math.Max(LOldCapacity, AMinCapacity + (TBitUtilities.Asr32(AMinCapacity, 1)));
+
+  System.SetLength(LCopy, LNewCapacity);
+  for I := 0 to FElementCount - 1 do
+    LCopy[I] := FElements[I];
+
+  FElements := LCopy;
+  FCopyOnWrite := False;
+end;
+
+class function TAsn1EncodableVector.FromCollection(const AC: TCryptoLibGenericArray<IAsn1Encodable>): IAsn1EncodableVector;
+var
+  LV: TAsn1EncodableVector;
+begin
+  LV := TAsn1EncodableVector.Create(System.Length(AC));
+  LV.AddAll(AC);
+  Result := LV;
+end;
+
+class function TAsn1EncodableVector.FromElement(const AElement: IAsn1Encodable): IAsn1EncodableVector;
+var
+  LV: TAsn1EncodableVector;
+begin
+  LV := TAsn1EncodableVector.Create(1);
+  LV.Add(AElement);
+  Result := LV;
+end;
+
+class function TAsn1EncodableVector.FromEnumerable(const AE: TCryptoLibGenericArray<IAsn1Encodable>): IAsn1EncodableVector;
+var
+  LV: TAsn1EncodableVector;
+begin
+  LV := TAsn1EncodableVector.Create();
+  LV.AddAll(AE);
+  Result := LV;
+end;
+
+class function TAsn1EncodableVector.CloneElements(const AElements: TCryptoLibGenericArray<IAsn1Encodable>): TCryptoLibGenericArray<IAsn1Encodable>;
+begin
+  Result := CopyElements(AElements, System.Length(AElements));
+end;
+
+class constructor TAsn1EncodableVector.Create;
+begin
+  FEmptyElements := nil;
+end;
+
+{ TAsn1Object }
+
+procedure TAsn1Object.EncodeTo(const AOutput: TStream);
+var
+  LAsn1Out: TAsn1OutputStream;
+begin
+  LAsn1Out := TAsn1OutputStream.CreateInstance(AOutput, TAsn1Encodable.Ber, True);
+  try
+    GetEncoding(LAsn1Out.Encoding).Encode(LAsn1Out);
+  finally
+    LAsn1Out.Free;
+  end;
+end;
+
+procedure TAsn1Object.EncodeTo(const AOutput: TStream; const AEncoding: String);
+var
+  LAsn1Out: TAsn1OutputStream;
+begin
+  LAsn1Out := TAsn1OutputStream.CreateInstance(AOutput, AEncoding, True);
+  try
+    GetEncoding(LAsn1Out.Encoding).Encode(LAsn1Out);
+  finally
+    LAsn1Out.Free;
+  end;
+end;
+
+function TAsn1Object.GetEncoded(const AEncoding: String; APreAlloc, APostAlloc: Int32): TCryptoLibByteArray;
+var
+  LEncodingType, LLength: Int32;
+  LAsn1Encoding: IAsn1Encoding;
+  LAsn1Out: TAsn1OutputStream;
+begin
+  LEncodingType := TAsn1OutputStream.GetEncodingType(AEncoding);
+  LAsn1Encoding := GetEncoding(LEncodingType);
+  LLength := LAsn1Encoding.GetLength();
+  System.SetLength(Result, APreAlloc + LLength + APostAlloc);
+  LAsn1Out := TAsn1OutputStream.CreateInstance(Result, APreAlloc, LLength, AEncoding, False);
+  try
+    LAsn1Encoding.Encode(LAsn1Out);
+    // Assert(LAsn1Out.Length = LAsn1Out.Position);
+  finally
+    LAsn1Out.Free;
+  end;
+end;
+
+function TAsn1Object.Equals(const AOther: IAsn1Object): Boolean;
+begin
+  Result := (Self as IAsn1Object) = AOther;
+  if not Result and (AOther <> nil) then
+    Result := Asn1Equals(AOther);
+end;
+
+class function TAsn1Object.FromByteArray(const AData: TCryptoLibByteArray): IAsn1Object;
+begin
+  Result := FromBufferStream(TFixedBufferStream.Create(AData, 0, System.Length(AData), False));
+end;
+
+class function TAsn1Object.FromBufferStream(const ABufferStream: TFixedBufferStream): IAsn1Object;
+var
+  LAsn1In: TAsn1InputStream;
+begin
+  LAsn1In := TAsn1InputStream.Create(ABufferStream);
+  try
+    Result := LAsn1In.ReadObject();
+    if LAsn1In.Position <> LAsn1In.Size then
+      raise EIOCryptoLibException.Create('extra data found after object');
+  finally
+    LAsn1In.Free;
+  end;
+end;
+
+class function TAsn1Object.FromStream(const AInStr: TStream): IAsn1Object;
+var
+  LLimit: Int32;
+  LAsn1In: TAsn1InputStream;
+begin
+  LLimit := TAsn1InputStream.FindLimit(AInStr);
+  LAsn1In := TAsn1InputStream.Create(AInStr, LLimit, True);
+  try
+    Result := LAsn1In.ReadObject();
+  finally
+    LAsn1In.Free;
+  end;
+end;
+
+function TAsn1Object.ToAsn1Object(): IAsn1Object;
+begin
+  Result := Self as IAsn1Object;
+end;
+
+function TAsn1Object.CallAsn1Equals(const AObj: IAsn1Object): Boolean;
+begin
+  Result := Asn1Equals(AObj);
+end;
+
+function TAsn1Object.CallAsn1GetHashCode(): Int32;
+begin
+  Result := Asn1GetHashCode();
+end;
+
+end.

+ 1 - 1
CryptoLib/src/Asn1/ClpAsn1Dumper.pas

@@ -26,7 +26,7 @@ uses
   SysUtils,
   Classes,
   ClpIAsn1Objects,
-  ClpAsn1Objects,
+  ClpIAsn1Core,
   ClpAsn1Utilities,
   ClpAsn1Streams,
   ClpEncoders,

+ 746 - 0
CryptoLib/src/Asn1/ClpAsn1Encodings.pas

@@ -0,0 +1,746 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpAsn1Encodings;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  Math,
+  SysUtils,
+  ClpCryptoLibTypes,
+  ClpIAsn1Encodings;
+
+type
+
+  /// <summary>
+  /// Abstract base class for DER encoding.
+  /// </summary>
+  TDerEncoding = class abstract(TInterfacedObject, IDerEncoding, IAsn1Encoding)
+  strict protected
+    FTagClass: Int32;
+    FTagNo: Int32;
+
+  strict protected
+    /// <summary>
+    /// Compare length and contents with another DER encoding.
+    /// </summary>
+    function CompareLengthAndContents(const AOther: IDerEncoding): Int32; virtual; abstract;
+
+  public
+    /// <summary>
+    /// Create a DER encoding.
+    /// </summary>
+    constructor Create(ATagClass, ATagNo: Int32);
+
+    /// <summary>
+    /// Get the tag class.
+    /// </summary>
+    function GetTagClass(): Int32;
+    /// <summary>
+    /// Get the tag number.
+    /// </summary>
+    function GetTagNo(): Int32;
+    /// <summary>
+    /// Compare this encoding with another.
+    /// </summary>
+    function CompareTo(const AOther: IDerEncoding): Int32;
+
+    /// <summary>
+    /// Encode to the given stream (must be a TAsn1OutputStream).
+    /// </summary>
+    procedure Encode(const AOut: TStream); virtual; abstract;
+
+    /// <summary>
+    /// Get the length of the encoded data.
+    /// </summary>
+    function GetLength(): Int32; virtual; abstract;
+
+    property TagClass: Int32 read FTagClass;
+    property TagNo: Int32 read FTagNo;
+  end;
+
+  /// <summary>
+  /// DL (Definite Length) constructed encoding.
+  /// </summary>
+  TConstructedDLEncoding = class sealed(TInterfacedObject, IAsn1Encoding)
+  strict private
+    FTagClass: Int32;
+    FTagNo: Int32;
+    FContentsElements: TCryptoLibGenericArray<IAsn1Encoding>;
+    FContentsLength: Int32;
+  public
+    constructor Create(ATagClass, ATagNo: Int32;
+      const AContentsElements: TCryptoLibGenericArray<IAsn1Encoding>);
+    procedure Encode(const AOut: TStream);
+    function GetLength(): Int32;
+  end;
+
+  /// <summary>
+  /// DL tagged encoding.
+  /// </summary>
+  TTaggedDLEncoding = class sealed(TInterfacedObject, IAsn1Encoding)
+  strict private
+    FTagClass: Int32;
+    FTagNo: Int32;
+    FContentsElement: IAsn1Encoding;
+    FContentsLength: Int32;
+  public
+    constructor Create(ATagClass, ATagNo: Int32;
+      const AContentsElement: IAsn1Encoding);
+    procedure Encode(const AOut: TStream);
+    function GetLength(): Int32;
+  end;
+
+  /// <summary>
+  /// DER constructed encoding.
+  /// </summary>
+  TConstructedDerEncoding = class sealed(TDerEncoding, IConstructedDerEncoding)
+  strict private
+    FContentsElements: TCryptoLibGenericArray<IDerEncoding>;
+    FContentsLength: Int32;
+  strict protected
+    function CompareLengthAndContents(const AOther: IDerEncoding): Int32; override;
+  public
+    constructor Create(ATagClass, ATagNo: Int32;
+      const AContentsElements: TCryptoLibGenericArray<IDerEncoding>);
+    procedure Encode(const AOut: TStream); override;
+    function GetLength(): Int32; override;
+    function GetContentsLength(): Int32;
+    function GetContentsElements(): TCryptoLibGenericArray<IDerEncoding>;
+  end;
+
+  /// <summary>
+  /// DER tagged encoding.
+  /// </summary>
+  TTaggedDerEncoding = class sealed(TDerEncoding, ITaggedDerEncoding)
+  strict private
+    FContentsElement: IDerEncoding;
+    FContentsLength: Int32;
+  strict protected
+    function CompareLengthAndContents(const AOther: IDerEncoding): Int32; override;
+  public
+    constructor Create(ATagClass, ATagNo: Int32;
+      const AContentsElement: IDerEncoding);
+    procedure Encode(const AOut: TStream); override;
+    function GetLength(): Int32; override;
+    function GetContentsLength(): Int32;
+    function GetContentsElement(): IDerEncoding;
+  end;
+
+  /// <summary>
+  /// IL (Indefinite Length) constructed encoding.
+  /// </summary>
+  TConstructedILEncoding = class sealed(TInterfacedObject, IAsn1Encoding)
+  strict private
+    FTagClass: Int32;
+    FTagNo: Int32;
+    FContentsElements: TCryptoLibGenericArray<IAsn1Encoding>;
+  public
+    constructor Create(ATagClass, ATagNo: Int32;
+      const AContentsElements: TCryptoLibGenericArray<IAsn1Encoding>);
+    procedure Encode(const AOut: TStream);
+    function GetLength(): Int32;
+  end;
+
+  /// <summary>
+  /// IL tagged encoding.
+  /// </summary>
+  TTaggedILEncoding = class sealed(TInterfacedObject, IAsn1Encoding)
+  strict private
+    FTagClass: Int32;
+    FTagNo: Int32;
+    FContentsElement: IAsn1Encoding;
+  public
+    constructor Create(ATagClass, ATagNo: Int32;
+      const AContentsElement: IAsn1Encoding);
+    procedure Encode(const AOut: TStream);
+    function GetLength(): Int32;
+  end;
+
+  /// <summary>
+  /// Primitive encoding.
+  /// </summary>
+  TPrimitiveEncoding = class sealed(TInterfacedObject, IAsn1Encoding)
+  strict private
+    FTagClass: Int32;
+    FTagNo: Int32;
+    FContentsOctets: TCryptoLibByteArray;
+  public
+    constructor Create(ATagClass, ATagNo: Int32;
+      const AContentsOctets: TCryptoLibByteArray);
+    procedure Encode(const AOut: TStream);
+    function GetLength(): Int32;
+  end;
+
+  /// <summary>
+  /// DER primitive encoding.
+  /// </summary>
+  TPrimitiveDerEncoding = class sealed(TDerEncoding, IPrimitiveDerEncoding)
+  protected
+    FContentsOctets: TCryptoLibByteArray;
+    function CompareLengthAndContents(const AOther: IDerEncoding): Int32; override;
+  public
+    constructor Create(ATagClass, ATagNo: Int32;
+      const AContentsOctets: TCryptoLibByteArray); overload;
+    procedure Encode(const AOut: TStream); override;
+    function GetLength(): Int32; override;
+    function GetContentsOctets(): TCryptoLibByteArray;
+  end;
+
+  /// <summary>
+  /// Primitive encoding with suffix.
+  /// </summary>
+  TPrimitiveEncodingSuffixed = class sealed(TInterfacedObject, IAsn1Encoding)
+  strict private
+    FTagClass: Int32;
+    FTagNo: Int32;
+    FContentsOctets: TCryptoLibByteArray;
+    FContentsSuffix: Byte;
+  public
+    constructor Create(ATagClass, ATagNo: Int32;
+      const AContentsOctets: TCryptoLibByteArray; AContentsSuffix: Byte);
+    procedure Encode(const AOut: TStream);
+    function GetLength(): Int32;
+  end;
+
+  /// <summary>
+  /// DER primitive encoding with suffix.
+  /// </summary>
+  TPrimitiveDerEncodingSuffixed = class sealed(TDerEncoding, IPrimitiveDerEncodingSuffixed)
+  protected
+    FContentsOctets: TCryptoLibByteArray;
+    FContentsSuffix: Byte;
+    function CompareLengthAndContents(const AOther: IDerEncoding): Int32; override;
+    class function CompareSuffixed(const AOctetsA: TCryptoLibByteArray;
+      ASuffixA: Byte; const AOctetsB: TCryptoLibByteArray; ASuffixB: Byte): Int32; static;
+  public
+    constructor Create(ATagClass, ATagNo: Int32;
+      const AContentsOctets: TCryptoLibByteArray; AContentsSuffix: Byte);
+    procedure Encode(const AOut: TStream); override;
+    function GetLength(): Int32; override;
+    function GetContentsOctets(): TCryptoLibByteArray;
+    function GetContentsSuffix(): Byte;
+  end;
+
+implementation
+
+uses
+  ClpAsn1Streams;
+
+const
+  // BER/DER constructed flag (bit 6)
+  CONSTRUCTED_FLAG = $20;
+
+{ TDerEncoding }
+
+constructor TDerEncoding.Create(ATagClass, ATagNo: Int32);
+begin
+  inherited Create;
+  FTagClass := ATagClass;
+  FTagNo := ATagNo;
+end;
+
+function TDerEncoding.GetTagClass(): Int32;
+begin
+  Result := FTagClass;
+end;
+
+function TDerEncoding.GetTagNo(): Int32;
+begin
+  Result := FTagNo;
+end;
+
+function TDerEncoding.CompareTo(const AOther: IDerEncoding): Int32;
+begin
+  if AOther = nil then
+  begin
+    Result := 1;
+    Exit;
+  end;
+
+  if FTagClass <> AOther.TagClass then
+  begin
+    Result := FTagClass - AOther.TagClass;
+    Exit;
+  end;
+
+  if FTagNo <> AOther.TagNo then
+  begin
+    Result := FTagNo - AOther.TagNo;
+    Exit;
+  end;
+
+  Result := CompareLengthAndContents(AOther);
+end;
+
+{ TConstructedDLEncoding }
+
+constructor TConstructedDLEncoding.Create(ATagClass, ATagNo: Int32;
+  const AContentsElements: TCryptoLibGenericArray<IAsn1Encoding>);
+begin
+  inherited Create;
+  FTagClass := ATagClass;
+  FTagNo := ATagNo;
+  FContentsElements := AContentsElements;
+  FContentsLength := TAsn1OutputStream.GetLengthOfContents(AContentsElements);
+end;
+
+procedure TConstructedDLEncoding.Encode(const AOut: TStream);
+var
+  LAsn1Out: TAsn1OutputStream;
+begin
+  LAsn1Out := TAsn1OutputStream.ValidateAsn1OutputStream(AOut);
+  LAsn1Out.WriteIdentifier(CONSTRUCTED_FLAG or FTagClass, FTagNo);
+  LAsn1Out.WriteDL(FContentsLength);
+  LAsn1Out.EncodeContents(FContentsElements);
+end;
+
+function TConstructedDLEncoding.GetLength(): Int32;
+begin
+  Result := TAsn1OutputStream.GetLengthOfEncodingDL(FTagNo, FContentsLength);
+end;
+
+{ TTaggedDLEncoding }
+
+constructor TTaggedDLEncoding.Create(ATagClass, ATagNo: Int32;
+  const AContentsElement: IAsn1Encoding);
+begin
+  inherited Create;
+  FTagClass := ATagClass;
+  FTagNo := ATagNo;
+  FContentsElement := AContentsElement;
+  FContentsLength := AContentsElement.GetLength();
+end;
+
+procedure TTaggedDLEncoding.Encode(const AOut: TStream);
+var
+  LAsn1Out: TAsn1OutputStream;
+begin
+  LAsn1Out := TAsn1OutputStream.ValidateAsn1OutputStream(AOut);
+  LAsn1Out.WriteIdentifier(CONSTRUCTED_FLAG or FTagClass, FTagNo);
+  LAsn1Out.WriteDL(FContentsLength);
+  FContentsElement.Encode(AOut);
+end;
+
+function TTaggedDLEncoding.GetLength(): Int32;
+begin
+  Result := TAsn1OutputStream.GetLengthOfEncodingDL(FTagNo, FContentsLength);
+end;
+
+{ TConstructedDerEncoding }
+
+constructor TConstructedDerEncoding.Create(ATagClass, ATagNo: Int32;
+  const AContentsElements: TCryptoLibGenericArray<IDerEncoding>);
+begin
+  inherited Create(ATagClass, ATagNo);
+  if AContentsElements = nil then
+    raise EArgumentNilCryptoLibException.Create('contentsElements');
+  FContentsElements := AContentsElements;
+  FContentsLength := TAsn1OutputStream.GetLengthOfContents(TCryptoLibGenericArray<IAsn1Encoding>(AContentsElements));
+end;
+
+function TConstructedDerEncoding.CompareLengthAndContents(const AOther: IDerEncoding): Int32;
+var
+  LThat: IConstructedDerEncoding;
+  I, LLength: Int32;
+begin
+  if not Supports(AOther, IConstructedDerEncoding, LThat) then
+    raise EInvalidOperationCryptoLibException.Create('Invalid type for comparison');
+
+  if FContentsLength <> LThat.ContentsLength then
+  begin
+    Result := FContentsLength - LThat.ContentsLength;
+    Exit;
+  end;
+
+  LLength := Math.Min(System.Length(FContentsElements), System.Length(LThat.ContentsElements));
+  for I := 0 to LLength - 1 do
+  begin
+    Result := FContentsElements[I].CompareTo(LThat.ContentsElements[I]);
+    if Result <> 0 then
+      Exit;
+  end;
+
+  Result := System.Length(FContentsElements) - System.Length(LThat.ContentsElements);
+end;
+
+procedure TConstructedDerEncoding.Encode(const AOut: TStream);
+var
+  LAsn1Out: TAsn1OutputStream;
+begin
+  LAsn1Out := TAsn1OutputStream.ValidateAsn1OutputStream(AOut);
+  LAsn1Out.WriteIdentifier(CONSTRUCTED_FLAG or FTagClass, FTagNo);
+  LAsn1Out.WriteDL(FContentsLength);
+  LAsn1Out.EncodeContents(TCryptoLibGenericArray<IAsn1Encoding>(FContentsElements));
+end;
+
+function TConstructedDerEncoding.GetLength(): Int32;
+begin
+  Result := TAsn1OutputStream.GetLengthOfEncodingDL(FTagNo, FContentsLength);
+end;
+
+function TConstructedDerEncoding.GetContentsLength(): Int32;
+begin
+  Result := FContentsLength;
+end;
+
+function TConstructedDerEncoding.GetContentsElements(): TCryptoLibGenericArray<IDerEncoding>;
+begin
+  Result := FContentsElements;
+end;
+
+{ TTaggedDerEncoding }
+
+constructor TTaggedDerEncoding.Create(ATagClass, ATagNo: Int32;
+  const AContentsElement: IDerEncoding);
+begin
+  inherited Create(ATagClass, ATagNo);
+  if AContentsElement = nil then
+    raise EArgumentNilCryptoLibException.Create('contentsElement');
+  FContentsElement := AContentsElement;
+  FContentsLength := AContentsElement.GetLength();
+end;
+
+function TTaggedDerEncoding.CompareLengthAndContents(const AOther: IDerEncoding): Int32;
+var
+  LThat: ITaggedDerEncoding;
+begin
+  if not Supports(AOther, ITaggedDerEncoding, LThat) then
+    raise EInvalidOperationCryptoLibException.Create('Invalid type for comparison');
+
+  if FContentsLength <> LThat.ContentsLength then
+  begin
+    Result := FContentsLength - LThat.ContentsLength;
+    Exit;
+  end;
+
+  Result := FContentsElement.CompareTo(LThat.ContentsElement);
+end;
+
+procedure TTaggedDerEncoding.Encode(const AOut: TStream);
+var
+  LAsn1Out: TAsn1OutputStream;
+begin
+  LAsn1Out := TAsn1OutputStream.ValidateAsn1OutputStream(AOut);
+  LAsn1Out.WriteIdentifier(CONSTRUCTED_FLAG or FTagClass, FTagNo);
+  LAsn1Out.WriteDL(FContentsLength);
+  FContentsElement.Encode(AOut);
+end;
+
+function TTaggedDerEncoding.GetLength(): Int32;
+begin
+  Result := TAsn1OutputStream.GetLengthOfEncodingDL(FTagNo, FContentsLength);
+end;
+
+function TTaggedDerEncoding.GetContentsLength(): Int32;
+begin
+  Result := FContentsLength;
+end;
+
+function TTaggedDerEncoding.GetContentsElement(): IDerEncoding;
+begin
+  Result := FContentsElement;
+end;
+
+{ TConstructedILEncoding }
+
+constructor TConstructedILEncoding.Create(ATagClass, ATagNo: Int32;
+  const AContentsElements: TCryptoLibGenericArray<IAsn1Encoding>);
+begin
+  inherited Create;
+  FTagClass := ATagClass;
+  FTagNo := ATagNo;
+  FContentsElements := AContentsElements;
+end;
+
+procedure TConstructedILEncoding.Encode(const AOut: TStream);
+var
+  LAsn1Out: TAsn1OutputStream;
+begin
+  LAsn1Out := TAsn1OutputStream.ValidateAsn1OutputStream(AOut);
+  LAsn1Out.WriteIdentifier(CONSTRUCTED_FLAG or FTagClass, FTagNo);
+  LAsn1Out.WriteByte($80);
+  LAsn1Out.EncodeContents(FContentsElements);
+  LAsn1Out.WriteByte($00);
+  LAsn1Out.WriteByte($00);
+end;
+
+function TConstructedILEncoding.GetLength(): Int32;
+begin
+  Result := TAsn1OutputStream.GetLengthOfEncodingIL(FTagNo, FContentsElements);
+end;
+
+{ TTaggedILEncoding }
+
+constructor TTaggedILEncoding.Create(ATagClass, ATagNo: Int32;
+  const AContentsElement: IAsn1Encoding);
+begin
+  inherited Create;
+  FTagClass := ATagClass;
+  FTagNo := ATagNo;
+  FContentsElement := AContentsElement;
+end;
+
+procedure TTaggedILEncoding.Encode(const AOut: TStream);
+var
+  LAsn1Out: TAsn1OutputStream;
+begin
+  LAsn1Out := TAsn1OutputStream.ValidateAsn1OutputStream(AOut);
+  LAsn1Out.WriteIdentifier(CONSTRUCTED_FLAG or FTagClass, FTagNo);
+  LAsn1Out.WriteByte($80);
+  FContentsElement.Encode(AOut);
+  LAsn1Out.WriteByte($00);
+  LAsn1Out.WriteByte($00);
+end;
+
+function TTaggedILEncoding.GetLength(): Int32;
+begin
+  Result := TAsn1OutputStream.GetLengthOfEncodingIL(FTagNo, FContentsElement);
+end;
+
+{ TPrimitiveEncoding }
+
+constructor TPrimitiveEncoding.Create(ATagClass, ATagNo: Int32;
+  const AContentsOctets: TCryptoLibByteArray);
+begin
+  inherited Create;
+  FTagClass := ATagClass;
+  FTagNo := ATagNo;
+  FContentsOctets := AContentsOctets;
+end;
+
+procedure TPrimitiveEncoding.Encode(const AOut: TStream);
+var
+  LAsn1Out: TAsn1OutputStream;
+begin
+  LAsn1Out := TAsn1OutputStream.ValidateAsn1OutputStream(AOut);
+  LAsn1Out.WriteIdentifier(FTagClass, FTagNo);
+  LAsn1Out.WriteDL(System.Length(FContentsOctets));
+  if System.Length(FContentsOctets) > 0 then
+    LAsn1Out.Write(FContentsOctets[0], System.Length(FContentsOctets));
+end;
+
+function TPrimitiveEncoding.GetLength(): Int32;
+begin
+  Result := TAsn1OutputStream.GetLengthOfEncodingDL(FTagNo, System.Length(FContentsOctets));
+end;
+
+{ TPrimitiveDerEncoding }
+
+constructor TPrimitiveDerEncoding.Create(ATagClass, ATagNo: Int32;
+  const AContentsOctets: TCryptoLibByteArray);
+begin
+  inherited Create(ATagClass, ATagNo);
+  if AContentsOctets = nil then
+    raise EArgumentNilCryptoLibException.Create('contentsOctets');
+  FContentsOctets := AContentsOctets;
+end;
+
+function TPrimitiveDerEncoding.CompareLengthAndContents(const AOther: IDerEncoding): Int32;
+var
+  LThat: IPrimitiveDerEncoding;
+  LSuffixed: IPrimitiveDerEncodingSuffixed;
+  I, LLength: Int32;
+  LThatOctets: TCryptoLibByteArray;
+begin
+  if Supports(AOther, IPrimitiveDerEncodingSuffixed, LSuffixed) then
+  begin
+    // Call the overridden method on the suffixed instance, passing Self
+    Result := -LSuffixed.CompareLengthAndContents(Self as IDerEncoding);
+    Exit;
+  end;
+
+  if not Supports(AOther, IPrimitiveDerEncoding, LThat) then
+    raise EInvalidOperationCryptoLibException.Create('Invalid type for comparison');
+
+  LThatOctets := LThat.ContentsOctets;
+  LLength := System.Length(FContentsOctets);
+  if LLength <> System.Length(LThatOctets) then
+  begin
+    Result := LLength - System.Length(LThatOctets);
+    Exit;
+  end;
+
+  for I := 0 to LLength - 1 do
+  begin
+    if FContentsOctets[I] <> LThatOctets[I] then
+    begin
+      Result := Int32(FContentsOctets[I]) - Int32(LThatOctets[I]);
+      Exit;
+    end;
+  end;
+
+  Result := 0;
+end;
+
+procedure TPrimitiveDerEncoding.Encode(const AOut: TStream);
+var
+  LAsn1Out: TAsn1OutputStream;
+begin
+  LAsn1Out := TAsn1OutputStream.ValidateAsn1OutputStream(AOut);
+  LAsn1Out.WriteIdentifier(FTagClass, FTagNo);
+  LAsn1Out.WriteDL(System.Length(FContentsOctets));
+  if System.Length(FContentsOctets) > 0 then
+    LAsn1Out.Write(FContentsOctets[0], System.Length(FContentsOctets));
+end;
+
+function TPrimitiveDerEncoding.GetLength(): Int32;
+begin
+  Result := TAsn1OutputStream.GetLengthOfEncodingDL(FTagNo, System.Length(FContentsOctets));
+end;
+
+function TPrimitiveDerEncoding.GetContentsOctets(): TCryptoLibByteArray;
+begin
+  Result := FContentsOctets;
+end;
+
+{ TPrimitiveEncodingSuffixed }
+
+constructor TPrimitiveEncodingSuffixed.Create(ATagClass, ATagNo: Int32;
+  const AContentsOctets: TCryptoLibByteArray; AContentsSuffix: Byte);
+begin
+  inherited Create;
+  FTagClass := ATagClass;
+  FTagNo := ATagNo;
+  FContentsOctets := AContentsOctets;
+  FContentsSuffix := AContentsSuffix;
+end;
+
+procedure TPrimitiveEncodingSuffixed.Encode(const AOut: TStream);
+var
+  LAsn1Out: TAsn1OutputStream;
+begin
+  LAsn1Out := TAsn1OutputStream.ValidateAsn1OutputStream(AOut);
+  LAsn1Out.WriteIdentifier(FTagClass, FTagNo);
+  LAsn1Out.WriteDL(System.Length(FContentsOctets));
+  if System.Length(FContentsOctets) > 1 then
+    LAsn1Out.Write(FContentsOctets[0], System.Length(FContentsOctets) - 1);
+  LAsn1Out.WriteByte(FContentsSuffix);
+end;
+
+function TPrimitiveEncodingSuffixed.GetLength(): Int32;
+begin
+  Result := TAsn1OutputStream.GetLengthOfEncodingDL(FTagNo, System.Length(FContentsOctets));
+end;
+
+{ TPrimitiveDerEncodingSuffixed }
+
+constructor TPrimitiveDerEncodingSuffixed.Create(ATagClass, ATagNo: Int32;
+  const AContentsOctets: TCryptoLibByteArray; AContentsSuffix: Byte);
+begin
+  inherited Create(ATagClass, ATagNo);
+  if AContentsOctets = nil then
+    raise EArgumentNilCryptoLibException.Create('contentsOctets');
+  if System.Length(AContentsOctets) = 0 then
+    raise EArgumentCryptoLibException.Create('contentsOctets length must be > 0');
+  FContentsOctets := AContentsOctets;
+  FContentsSuffix := AContentsSuffix;
+end;
+
+function TPrimitiveDerEncodingSuffixed.CompareLengthAndContents(const AOther: IDerEncoding): Int32;
+var
+  LSuff: IPrimitiveDerEncodingSuffixed;
+  LThat: IPrimitiveDerEncoding;
+  LThatOctets: TCryptoLibByteArray;
+  LLength: Int32;
+begin
+  if Supports(AOther, IPrimitiveDerEncodingSuffixed, LSuff) then
+  begin
+    Result := CompareSuffixed(FContentsOctets, FContentsSuffix,
+      LSuff.ContentsOctets, LSuff.ContentsSuffix);
+    Exit;
+  end;
+
+  if Supports(AOther, IPrimitiveDerEncoding, LThat) then
+  begin
+    LThatOctets := LThat.ContentsOctets;
+    LLength := System.Length(LThatOctets);
+    if LLength = 0 then
+    begin
+      Result := System.Length(FContentsOctets);
+      Exit;
+    end;
+
+    Result := CompareSuffixed(FContentsOctets, FContentsSuffix,
+      LThatOctets, LThatOctets[LLength - 1]);
+    Exit;
+  end;
+
+  raise EInvalidOperationCryptoLibException.Create('Invalid type for comparison');
+end;
+
+class function TPrimitiveDerEncodingSuffixed.CompareSuffixed(const AOctetsA: TCryptoLibByteArray;
+  ASuffixA: Byte; const AOctetsB: TCryptoLibByteArray; ASuffixB: Byte): Int32;
+var
+  LLength, I, LLast: Int32;
+begin
+  if (System.Length(AOctetsA) = 0) or (System.Length(AOctetsB) = 0) then
+    raise EArgumentCryptoLibException.Create('Octets length must be > 0');
+
+  LLength := System.Length(AOctetsA);
+  if LLength <> System.Length(AOctetsB) then
+  begin
+    Result := LLength - System.Length(AOctetsB);
+    Exit;
+  end;
+
+  LLast := LLength - 1;
+  for I := 0 to LLast - 1 do
+  begin
+    if AOctetsA[I] <> AOctetsB[I] then
+    begin
+      Result := Int32(AOctetsA[I]) - Int32(AOctetsB[I]);
+      Exit;
+    end;
+  end;
+
+  Result := Int32(ASuffixA) - Int32(ASuffixB);
+end;
+
+procedure TPrimitiveDerEncodingSuffixed.Encode(const AOut: TStream);
+var
+  LAsn1Out: TAsn1OutputStream;
+begin
+  LAsn1Out := TAsn1OutputStream.ValidateAsn1OutputStream(AOut);
+  LAsn1Out.WriteIdentifier(FTagClass, FTagNo);
+  LAsn1Out.WriteDL(System.Length(FContentsOctets));
+  if System.Length(FContentsOctets) > 1 then
+    LAsn1Out.Write(FContentsOctets[0], System.Length(FContentsOctets) - 1);
+  LAsn1Out.WriteByte(FContentsSuffix);
+end;
+
+function TPrimitiveDerEncodingSuffixed.GetLength(): Int32;
+begin
+  Result := TAsn1OutputStream.GetLengthOfEncodingDL(FTagNo, System.Length(FContentsOctets));
+end;
+
+function TPrimitiveDerEncodingSuffixed.GetContentsOctets(): TCryptoLibByteArray;
+begin
+  Result := FContentsOctets;
+end;
+
+function TPrimitiveDerEncodingSuffixed.GetContentsSuffix(): Byte;
+begin
+  Result := FContentsSuffix;
+end;
+
+end.
+

Разница между файлами не показана из-за своего большого размера
+ 87 - 1764
CryptoLib/src/Asn1/ClpAsn1Objects.pas


+ 1298 - 0
CryptoLib/src/Asn1/ClpAsn1Parsers.pas

@@ -0,0 +1,1298 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpAsn1Parsers;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  ClpCryptoLibTypes,
+  ClpAsn1Tags,
+  ClpIAsn1Core,
+  ClpIAsn1Objects,
+  ClpIAsn1Parsers,
+  ClpAsn1Core,
+  ClpAsn1Streams;
+
+type
+  /// <summary>
+  /// ASN.1 stream parser for reading ASN.1 objects from a stream.
+  /// </summary>
+  TAsn1StreamParser = class sealed(TInterfacedObject, IAsn1StreamParser)
+  strict private
+    FIn: TStream;
+    FLimit: Int32;
+    FTmpBuffers: TCryptoLibMatrixByteArray;
+
+    procedure Set00Check(AEnabled: Boolean);
+    function ImplParseObject(ATagHdr: Int32): IAsn1Convertible;
+    function ParseImplicitPrimitive(AUnivTagNo: Int32;
+      const ADefIn: TAsn1DefiniteLengthInputStream): IAsn1Convertible; overload;
+
+  public
+    /// <summary>
+    /// Create an ASN.1 stream parser from a stream.
+    /// </summary>
+    constructor Create(const AInput: TStream); overload;
+    /// <summary>
+    /// Create an ASN.1 stream parser from a byte array.
+    /// </summary>
+    constructor Create(const AEncoding: TCryptoLibByteArray); overload;
+    /// <summary>
+    /// Create an ASN.1 stream parser from a stream with a limit.
+    /// </summary>
+    constructor Create(const AInput: TStream; ALimit: Int32); overload;
+    /// <summary>
+    /// Public constructor with TmpBuffers.
+    /// </summary>
+    constructor Create(const AInput: TStream; ALimit: Int32;
+      const ATmpBuffers: TCryptoLibMatrixByteArray); overload;
+
+    destructor Destroy; override;
+
+    /// <summary>
+    /// Read the next object from the stream.
+    /// </summary>
+    function ReadObject(): IAsn1Convertible; virtual;
+    /// <summary>
+    /// Parse an object with a specific universal tag number.
+    /// </summary>
+    function ParseObject(AUnivTagNo: Int32): IAsn1Convertible;
+    /// <summary>
+    /// Parse an implicit constructed indefinite-length object.
+    /// </summary>
+    function ParseImplicitConstructedIL(AUnivTagNo: Int32): IAsn1Convertible;
+    /// <summary>
+    /// Parse an implicit constructed definite-length object.
+    /// </summary>
+    function ParseImplicitConstructedDL(AUnivTagNo: Int32): IAsn1Convertible;
+    /// <summary>
+    /// Parse an implicit primitive object.
+    /// </summary>
+    function ParseImplicitPrimitive(AUnivTagNo: Int32): IAsn1Convertible; overload;
+    /// <summary>
+    /// Parse a tagged object.
+    /// </summary>
+    function ParseTaggedObject(): IAsn1TaggedObjectParser;
+    /// <summary>
+    /// Load a tagged object with definite length.
+    /// </summary>
+    function LoadTaggedDL(ATagClass, ATagNo: Int32; AConstructed: Boolean): IAsn1Object;
+    /// <summary>
+    /// Load a tagged object with indefinite length.
+    /// </summary>
+    function LoadTaggedIL(ATagClass, ATagNo: Int32): IAsn1Object;
+
+  strict private
+    /// <summary>
+    /// Read a vector of ASN.1 objects.
+    /// </summary>
+    function ReadVector(): IAsn1EncodableVector;
+  end;
+
+
+  /// <summary>
+  /// Base class for ASN.1 bit string parsers.
+  /// </summary>
+  TAsn1BitStringParser = class abstract(TInterfacedObject, IAsn1BitStringParser)
+  public
+    /// <summary>
+    /// Return a stream representing the contents of the BIT STRING.
+    /// </summary>
+    function GetBitStream(): TStream; virtual; abstract;
+    /// <summary>
+    /// Return a stream representing the contents of the BIT STRING, where the content is
+    /// expected to be octet-aligned.
+    /// </summary>
+    function GetOctetStream(): TStream; virtual; abstract;
+    /// <summary>
+    /// Return the number of pad bits in the final byte.
+    /// </summary>
+    function GetPadBits(): Int32; virtual; abstract;
+    /// <summary>
+    /// Convert to ASN.1 object.
+    /// </summary>
+    function ToAsn1Object(): IAsn1Object; virtual; abstract;
+
+    property PadBits: Int32 read GetPadBits;
+  end;
+
+  /// <summary>
+  /// Base class for ASN.1 octet string parsers.
+  /// </summary>
+  TAsn1OctetStringParser = class abstract(TInterfacedObject, IAsn1OctetStringParser)
+  public
+    /// <summary>
+    /// Return the content of the OCTET STRING as a stream.
+    /// </summary>
+    function GetOctetStream(): TStream; virtual; abstract;
+    /// <summary>
+    /// Convert to ASN.1 object.
+    /// </summary>
+    function ToAsn1Object(): IAsn1Object; virtual; abstract;
+  end;
+
+  /// <summary>
+  /// Parser for BER bit strings.
+  /// </summary>
+  TBerBitStringParser = class sealed(TAsn1BitStringParser, IAsn1Convertible, IAsn1BitStringParser, IBerBitStringParser)
+  strict private
+    FParser: IAsn1StreamParser;
+    FBitStream: TAsn1ConstructedBitStream;
+
+  public
+    /// <summary>
+    /// Create a BER bit string parser.
+    /// </summary>
+    constructor Create(const AParser: IAsn1StreamParser);
+
+    /// <summary>
+    /// Return a <see cref="Stream"/> representing the contents of the BIT STRING. The final byte, if any,
+    /// may include pad bits. See <see cref="PadBits"/>.
+    /// </summary>
+    /// <remarks>
+    ///  Returns NEW stream - caller owns it and MUST free it.
+    /// </remarks>
+    /// <returns>A <see cref="Stream"/> with its source as the BIT STRING content.</returns>
+    function GetBitStream(): TStream; override;
+    /// <summary>Return a <see cref="Stream"/> representing the contents of the BIT STRING, where the content is
+    /// expected to be octet-aligned (this will be automatically checked during parsing).
+    ///</summary>
+    /// <remarks>
+    ///  Returns NEW stream - caller owns it and MUST free it.
+    /// </remarks>
+    /// <returns>A <see cref="Stream"/> with its source as the BIT STRING content.</returns>
+    function GetOctetStream(): TStream; override;
+    /// <summary>
+    /// Return the number of pad bits, if any, in the final byte, if any, read from
+    /// <see cref="GetBitStream"/>.
+    /// </summary>
+    /// <remarks>
+    /// This number is in the range zero to seven. That number of the least significant bits of the final byte, if
+    /// any, are not part of the contents and should be ignored. NOTE: Must be called AFTER the stream has been
+    /// fully processed (before it is freed). (Does not need to be called if <see cref="GetOctetStream"/> was used instead of
+    /// <see cref="GetBitStream"/>.
+    /// </remarks>
+    /// <returns>The number of pad bits. In the range zero to seven.</returns>
+    function GetPadBits(): Int32; override;
+    /// <summary>
+    /// Convert to ASN.1 object.
+    /// </summary>
+    function ToAsn1Object(): IAsn1Object; override;
+    /// <summary>
+    /// Parse a BER bit string from a stream parser.
+    /// </summary>
+    class function Parse(const ASp: IAsn1StreamParser): IBerBitString; static;
+  end;
+
+  /// <summary>
+  /// Parser for BER octet strings.
+  /// </summary>
+  TBerOctetStringParser = class sealed(TAsn1OctetStringParser, IAsn1Convertible, IAsn1OctetStringParser, IBerOctetStringParser)
+  strict private
+    FParser: IAsn1StreamParser;
+
+  public
+    /// <summary>
+    /// Create a BER octet string parser.
+    /// </summary>
+    constructor Create(const AParser: IAsn1StreamParser);
+
+    /// <summary>
+    /// Get the octet stream. Returns a NEW stream - caller owns it.
+    /// </summary>
+    function GetOctetStream(): TStream; override;
+    /// <summary>
+    /// Convert to ASN.1 object.
+    /// </summary>
+    function ToAsn1Object(): IAsn1Object; override;
+    /// <summary>
+    /// Parse a BER octet string from a stream parser.
+    /// </summary>
+    class function Parse(const ASp: IAsn1StreamParser): IBerOctetString; static;
+  end;
+
+  /// <summary>
+  /// Parser for DER octet strings.
+  /// </summary>
+  TDerOctetStringParser = class sealed(TAsn1OctetStringParser, IAsn1Convertible, IAsn1OctetStringParser)
+  strict private
+    FStream: TAsn1DefiniteLengthInputStream;
+
+  public
+    /// <summary>
+    /// Create a DER octet string parser.
+    /// </summary>
+    constructor Create(const AStream: TAsn1DefiniteLengthInputStream);
+
+    destructor Destroy; override;
+
+    /// <summary>
+    /// Get the octet stream.
+    /// </summary>
+    function GetOctetStream(): TStream; override;
+    /// <summary>
+    /// Convert to ASN.1 object.
+    /// </summary>
+    function ToAsn1Object(): IAsn1Object; override;
+  end;
+
+  /// <summary>
+  /// Parser for DL bit strings.
+  /// </summary>
+  TDLBitStringParser = class sealed(TAsn1BitStringParser, IAsn1Convertible, IAsn1BitStringParser)
+  strict private
+    FStream: TAsn1DefiniteLengthInputStream;
+    FPadBits: Int32;
+
+    function GetBitStreamInternal(AOctetAligned: Boolean): TStream;
+
+  public
+    /// <summary>
+    /// Create a DL bit string parser.
+    /// </summary>
+    constructor Create(const AStream: TAsn1DefiniteLengthInputStream);
+
+    destructor Destroy; override;
+
+    /// <summary>
+    /// Get the bit stream.
+    /// </summary>
+    function GetBitStream(): TStream; override;
+    /// <summary>
+    /// Get the octet stream.
+    /// </summary>
+    function GetOctetStream(): TStream; override;
+    /// <summary>
+    /// Get the number of pad bits.
+    /// </summary>
+    function GetPadBits(): Int32; override;
+    /// <summary>
+    /// Convert to ASN.1 object.
+    /// </summary>
+    function ToAsn1Object(): IAsn1Object; override;
+  end;
+
+  /// <summary>
+  /// Parser for DER sequences.
+  /// </summary>
+  TDerSequenceParser = class sealed(TInterfacedObject, IAsn1Convertible, IAsn1SequenceParser, IDerSequenceParser)
+  strict private
+    FParser: IAsn1StreamParser;
+
+  public
+    /// <summary>
+    /// Create a DER sequence parser.
+    /// </summary>
+    constructor Create(const AParser: IAsn1StreamParser);
+
+    /// <summary>
+    /// Read the next object from the sequence.
+    /// </summary>
+    function ReadObject(): IAsn1Convertible;
+    /// <summary>
+    /// Convert to ASN.1 object.
+    /// </summary>
+    function ToAsn1Object(): IAsn1Object;
+  end;
+
+  /// <summary>
+  /// Parser for DER sets.
+  /// </summary>
+  TDerSetParser = class sealed(TInterfacedObject, IAsn1Convertible, IAsn1SetParser, IDerSetParser)
+  strict private
+    FParser: IAsn1StreamParser;
+
+  public
+    /// <summary>
+    /// Create a DER set parser.
+    /// </summary>
+    constructor Create(const AParser: IAsn1StreamParser);
+
+    /// <summary>
+    /// Read the next object from the set.
+    /// </summary>
+    function ReadObject(): IAsn1Convertible;
+    /// <summary>
+    /// Convert to ASN.1 object.
+    /// </summary>
+    function ToAsn1Object(): IAsn1Object;
+  end;
+
+  /// <summary>
+  /// Parser for BER sequences.
+  /// </summary>
+  TBerSequenceParser = class sealed(TInterfacedObject, IAsn1Convertible, IAsn1SequenceParser, IBerSequenceParser)
+  strict private
+    FParser: IAsn1StreamParser;
+
+  public
+    /// <summary>
+    /// Create a BER sequence parser.
+    /// </summary>
+    constructor Create(const AParser: IAsn1StreamParser);
+
+    /// <summary>
+    /// Read the next object from the sequence.
+    /// </summary>
+    function ReadObject(): IAsn1Convertible;
+    /// <summary>
+    /// Convert to ASN.1 object.
+    /// </summary>
+    function ToAsn1Object(): IAsn1Object;
+    /// <summary>
+    /// Parse a BER sequence from a stream parser.
+    /// </summary>
+    class function Parse(const ASp: IAsn1StreamParser): IBerSequence; static;
+  end;
+
+  /// <summary>
+  /// Parser for BER sets.
+  /// </summary>
+  TBerSetParser = class sealed(TInterfacedObject, IAsn1Convertible, IAsn1SetParser, IBerSetParser)
+  strict private
+    FParser: IAsn1StreamParser;
+
+  public
+    /// <summary>
+    /// Create a BER set parser.
+    /// </summary>
+    constructor Create(const AParser: IAsn1StreamParser);
+
+    /// <summary>
+    /// Read the next object from the set.
+    /// </summary>
+    function ReadObject(): IAsn1Convertible;
+    /// <summary>
+    /// Convert to ASN.1 object.
+    /// </summary>
+    function ToAsn1Object(): IAsn1Object;
+    /// <summary>
+    /// Parse a BER set from a stream parser.
+    /// </summary>
+    class function Parse(const ASp: IAsn1StreamParser): IBerSet; static;
+  end;
+
+  /// <summary>
+  /// Parser for DER external objects.
+  /// </summary>
+  TDerExternalParser = class sealed(TAsn1Encodable, IDerExternalParser)
+  strict private
+    FParser: IAsn1StreamParser;
+
+  public
+    /// <summary>
+    /// Create a DER external parser.
+    /// </summary>
+    constructor Create(const AParser: IAsn1StreamParser);
+
+    /// <summary>
+    /// Read the next object.
+    /// </summary>
+    function ReadObject(): IAsn1Convertible;
+    /// <summary>
+    /// Convert to ASN.1 object.
+    /// </summary>
+    function ToAsn1Object(): IAsn1Object; override;
+    /// <summary>
+    /// Parse a DER external from a stream parser.
+    /// </summary>
+    class function Parse(const ASp: IAsn1StreamParser): IDerExternal; static;
+  end;
+
+  /// <summary>
+  /// Parser for BER tagged objects.
+  /// </summary>
+  TBerTaggedObjectParser = class(TInterfacedObject, IAsn1Convertible, IAsn1TaggedObjectParser, IBerTaggedObjectParser)
+  strict protected
+    FTagClass: Int32;
+    FTagNo: Int32;
+    FParser: IAsn1StreamParser;
+
+  public
+    /// <summary>
+    /// Create a BER tagged object parser.
+    /// </summary>
+    constructor Create(ATagClass, ATagNo: Int32; const AParser: IAsn1StreamParser);
+
+    /// <summary>
+    /// Get the tag class.
+    /// </summary>
+    function GetTagClass(): Int32;
+    /// <summary>
+    /// Get the tag number.
+    /// </summary>
+    function GetTagNo(): Int32;
+    /// <summary>
+    /// Check if this is a constructed object.
+    /// </summary>
+    function GetIsConstructed(): Boolean; virtual;
+    /// <summary>
+    /// Check if this has a context tag.
+    /// </summary>
+    function HasContextTag(ATagNo: Int32): Boolean;
+    /// <summary>
+    /// Check if this has the specified tag.
+    /// </summary>
+    function HasTag(ATagClass, ATagNo: Int32): Boolean; virtual;
+    /// <summary>
+    /// Parse a base universal object.
+    /// </summary>
+    function ParseBaseUniversal(ADeclaredExplicit: Boolean; ABaseTagNo: Int32): IAsn1Convertible; virtual;
+    /// <summary>
+    /// Parse an explicit base object.
+    /// </summary>
+    function ParseExplicitBaseObject(): IAsn1Convertible; virtual;
+    /// <summary>
+    /// Parse an explicit base tagged object.
+    /// </summary>
+    function ParseExplicitBaseTagged(): IAsn1TaggedObjectParser; virtual;
+    /// <summary>
+    /// Parse an implicit base tagged object.
+    /// </summary>
+    function ParseImplicitBaseTagged(ABaseTagClass, ABaseTagNo: Int32): IAsn1TaggedObjectParser; virtual;
+    /// <summary>
+    /// Convert to ASN.1 object.
+    /// </summary>
+    function ToAsn1Object(): IAsn1Object; virtual;
+
+    property TagClass: Int32 read GetTagClass;
+    property TagNo: Int32 read GetTagNo;
+  end;
+
+  /// <summary>
+  /// Parser for DL tagged objects.
+  /// </summary>
+  TDLTaggedObjectParser = class sealed(TBerTaggedObjectParser, IAsn1TaggedObjectParser, IDLTaggedObjectParser)
+  strict private
+    FConstructed: Boolean;
+
+    function CheckConstructed(): IAsn1StreamParser;
+
+  public
+    /// <summary>
+    /// Check if this is a constructed object.
+    /// </summary>
+    function GetIsConstructed(): Boolean; override;
+    /// <summary>
+    /// Create a DL tagged object parser.
+    /// </summary>
+    constructor Create(ATagClass, ATagNo: Int32; AConstructed: Boolean;
+      const AParser: IAsn1StreamParser);
+
+    /// <summary>
+    /// Parse a base universal object.
+    /// </summary>
+    function ParseBaseUniversal(ADeclaredExplicit: Boolean; ABaseTagNo: Int32): IAsn1Convertible; override;
+    /// <summary>
+    /// Parse an explicit base object.
+    /// </summary>
+    function ParseExplicitBaseObject(): IAsn1Convertible; override;
+    /// <summary>
+    /// Parse an explicit base tagged object.
+    /// </summary>
+    function ParseExplicitBaseTagged(): IAsn1TaggedObjectParser; override;
+    /// <summary>
+    /// Parse an implicit base tagged object.
+    /// </summary>
+    function ParseImplicitBaseTagged(ABaseTagClass, ABaseTagNo: Int32): IAsn1TaggedObjectParser; override;
+    /// <summary>
+    /// Convert to ASN.1 object.
+    /// </summary>
+    function ToAsn1Object(): IAsn1Object; override;
+  end;
+
+implementation
+
+uses
+  ClpAsn1Objects,
+  ClpStreamUtilities,
+
+  ClpStreams;
+
+{ TAsn1StreamParser }
+
+constructor TAsn1StreamParser.Create(const AInput: TStream);
+begin
+  Create(AInput, TAsn1InputStream.FindLimit(AInput));
+end;
+
+constructor TAsn1StreamParser.Create(const AEncoding: TCryptoLibByteArray);
+begin
+  Create(TFixedBufferStream.Create(AEncoding, 0, System.Length(AEncoding), False), System.Length(AEncoding));
+end;
+
+constructor TAsn1StreamParser.Create(const AInput: TStream; ALimit: Int32);
+var
+  LTmpBuffers: TCryptoLibMatrixByteArray;
+  I: Int32;
+begin
+  System.SetLength(LTmpBuffers, 16);
+  for I := 0 to System.Length(LTmpBuffers) - 1 do
+    System.SetLength(LTmpBuffers[I], 0);
+  Create(AInput, ALimit, LTmpBuffers);
+end;
+
+constructor TAsn1StreamParser.Create(const AInput: TStream; ALimit: Int32;
+  const ATmpBuffers: TCryptoLibMatrixByteArray);
+begin
+  inherited Create;
+  if not AInput.CanRead then
+    raise EArgumentCryptoLibException.Create('Expected stream to be readable');
+
+  FIn := AInput;
+  FLimit := ALimit;
+  FTmpBuffers := ATmpBuffers;
+end;
+
+destructor TAsn1StreamParser.Destroy;
+begin
+  // Parser ALWAYS owns and frees its stream
+  if FIn <> nil then
+  begin
+    FIn.Free;
+    FIn := nil;
+  end;
+  inherited Destroy;
+end;
+
+function TAsn1StreamParser.ReadObject(): IAsn1Convertible;
+var
+  LTagHdr: Int32;
+begin
+  LTagHdr := FIn.ReadByte();
+  if LTagHdr < 0 then
+  begin
+    Result := nil;
+    Exit;
+  end;
+
+  Result := ImplParseObject(LTagHdr);
+end;
+
+procedure TAsn1StreamParser.Set00Check(AEnabled: Boolean);
+var
+  LIndefiniteLengthInputStream: TAsn1IndefiniteLengthInputStream;
+begin
+  if FIn is TAsn1IndefiniteLengthInputStream then
+  begin
+    LIndefiniteLengthInputStream := FIn as TAsn1IndefiniteLengthInputStream;
+    LIndefiniteLengthInputStream.SetEofOn00(AEnabled);
+  end;
+end;
+
+function TAsn1StreamParser.ImplParseObject(ATagHdr: Int32): IAsn1Convertible;
+var
+  LTagNo, LLength, LTagClass: Int32;
+  LIndIn: TAsn1IndefiniteLengthInputStream;
+  LDefIn: TAsn1DefiniteLengthInputStream;
+  LSp: IAsn1StreamParser;
+  LIsConstructed: Boolean;
+begin
+  // turn off looking for "00" while we resolve the tag
+  Set00Check(False);
+
+  // calculate tag number
+  LTagNo := TAsn1InputStream.ReadTagNumber(FIn, ATagHdr);
+
+  // calculate length
+  LLength := TAsn1InputStream.ReadLength(FIn, FLimit,
+    (LTagNo = TAsn1Tags.BitString) or (LTagNo = TAsn1Tags.OctetString) or
+    (LTagNo = TAsn1Tags.Sequence) or (LTagNo = TAsn1Tags.&Set) or
+    (LTagNo = TAsn1Tags.External));
+
+  if LLength < 0 then // indefinite-length method
+  begin
+    if 0 = (ATagHdr and TAsn1Tags.Constructed) then
+      raise EIOCryptoLibException.Create
+        ('indefinite-length primitive encoding encountered');
+
+    LIndIn := TAsn1IndefiniteLengthInputStream.Create(FIn, FLimit);
+    try
+      LSp := TAsn1StreamParser.Create(LIndIn, FLimit, FTmpBuffers);
+    except
+      LIndIn.Free;
+      raise;
+    end;
+
+    LTagClass := ATagHdr and TAsn1Tags.Private;
+    if 0 <> LTagClass then
+    begin
+      Result := TBerTaggedObjectParser.Create(LTagClass, LTagNo, LSp);
+      Exit;
+    end;
+
+    Result := LSp.ParseImplicitConstructedIL(LTagNo);
+  end
+  else
+  begin
+    LDefIn := TAsn1DefiniteLengthInputStream.Create(FIn, LLength, FLimit);
+
+    if 0 = (ATagHdr and TAsn1Tags.Flags) then
+    begin
+      try
+        Result := ParseImplicitPrimitive(LTagNo, LDefIn);
+      except
+        LDefIn.Free;
+        raise;
+      end;
+      Exit;
+    end;
+
+    try
+      LSp := TAsn1StreamParser.Create(LDefIn, LDefIn.Remaining, FTmpBuffers);
+    except
+      LDefIn.Free;
+      raise;
+    end;
+
+    LTagClass := ATagHdr and TAsn1Tags.Private;
+    if 0 <> LTagClass then
+    begin
+      LIsConstructed := (ATagHdr and TAsn1Tags.Constructed) <> 0;
+      Result := TDLTaggedObjectParser.Create(LTagClass, LTagNo, LIsConstructed, LSp);
+      Exit;
+    end;
+
+    Result := LSp.ParseImplicitConstructedDL(LTagNo);
+  end;
+end;
+
+function TAsn1StreamParser.ParseImplicitConstructedDL(AUnivTagNo: Int32)
+  : IAsn1Convertible;
+begin
+  case AUnivTagNo of
+    TAsn1Tags.BitString:
+      // TODO[asn1] DLConstructedBitStringParser
+      Result := TBerBitStringParser.Create(Self as IAsn1StreamParser);
+    TAsn1Tags.External:
+      // TODO[asn1] DLExternalParser
+      Result := TDerExternalParser.Create(Self as IAsn1StreamParser);
+    TAsn1Tags.OctetString:
+      // TODO[asn1] DLConstructedOctetStringParser
+      Result := TBerOctetStringParser.Create(Self as IAsn1StreamParser);
+    TAsn1Tags.&Set:
+      // TODO[asn1] DLSetParser
+      Result := TDerSetParser.Create(Self as IAsn1StreamParser);
+    TAsn1Tags.Sequence:
+      // TODO[asn1] DLSequenceParser
+      Result := TDerSequenceParser.Create(Self as IAsn1StreamParser);
+  else
+    raise EAsn1CryptoLibException.CreateFmt
+      ('unknown DL object encountered: 0x%x', [AUnivTagNo]);
+  end;
+end;
+
+function TAsn1StreamParser.ParseImplicitConstructedIL(AUnivTagNo: Int32)
+  : IAsn1Convertible;
+begin
+  case AUnivTagNo of
+    TAsn1Tags.BitString:
+      Result := TBerBitStringParser.Create(Self as IAsn1StreamParser);
+    TAsn1Tags.External:
+      // TODO[asn1] BERExternalParser
+      Result := TDerExternalParser.Create(Self as IAsn1StreamParser);
+    TAsn1Tags.OctetString:
+      Result := TBerOctetStringParser.Create(Self as IAsn1StreamParser);
+    TAsn1Tags.Sequence:
+      Result := TBerSequenceParser.Create(Self as IAsn1StreamParser);
+    TAsn1Tags.&Set:
+      Result := TBerSetParser.Create(Self as IAsn1StreamParser);
+  else
+    raise EAsn1CryptoLibException.CreateFmt
+      ('unknown BER object encountered: 0x%x', [AUnivTagNo]);
+  end;
+end;
+
+function TAsn1StreamParser.ParseImplicitPrimitive(AUnivTagNo: Int32)
+  : IAsn1Convertible;
+begin
+  if FIn is TAsn1DefiniteLengthInputStream then
+    Result := ParseImplicitPrimitive(AUnivTagNo,
+      FIn as TAsn1DefiniteLengthInputStream)
+  else
+    raise EAsn1CryptoLibException.Create
+      ('ParseImplicitPrimitive requires DefiniteLengthInputStream');
+end;
+
+function TAsn1StreamParser.ParseImplicitPrimitive(AUnivTagNo: Int32;
+  const ADefIn: TAsn1DefiniteLengthInputStream): IAsn1Convertible;
+begin
+  // Some primitive encodings can be handled by parsers too...
+  case AUnivTagNo of
+    TAsn1Tags.BitString:
+      Result := TDLBitStringParser.Create(ADefIn);
+    TAsn1Tags.External:
+      raise EAsn1CryptoLibException.Create
+        ('externals must use constructed encoding (see X.690 8.18)');
+    TAsn1Tags.OctetString:
+      Result := TDerOctetStringParser.Create(ADefIn);
+    TAsn1Tags.&Set:
+      raise EAsn1CryptoLibException.Create
+        ('sequences must use constructed encoding (see X.690 8.9.1/8.10.1)');
+    TAsn1Tags.Sequence:
+      raise EAsn1CryptoLibException.Create
+        ('sets must use constructed encoding (see X.690 8.11.1/8.12.1)');
+  else
+    begin
+      try
+        Result := TAsn1InputStream.CreatePrimitiveDerObject(AUnivTagNo, ADefIn, FTmpBuffers);
+        ADefIn.Free;
+      except
+        on e: EArgumentCryptoLibException do
+          raise EAsn1CryptoLibException.Create('corrupted stream detected: ' + e.Message);
+      end;
+    end;
+  end;
+end;
+
+function TAsn1StreamParser.LoadTaggedDL(ATagClass, ATagNo: Int32; AConstructed: Boolean): IAsn1Object;
+var
+  LContentsOctets: TCryptoLibByteArray;
+  LDefIn: TAsn1DefiniteLengthInputStream;
+  LContentsElements: IAsn1EncodableVector;
+begin
+  if not AConstructed then
+  begin
+    LDefIn := FIn as TAsn1DefiniteLengthInputStream;
+    LContentsOctets := LDefIn.ToArray();
+    Result := TAsn1TaggedObject.CreatePrimitive(ATagClass, ATagNo, LContentsOctets);
+  end
+  else
+  begin
+    LContentsElements := ReadVector();
+    Result := TAsn1TaggedObject.CreateConstructedDL(ATagClass, ATagNo, LContentsElements);
+  end;
+end;
+
+function TAsn1StreamParser.LoadTaggedIL(ATagClass, ATagNo: Int32): IAsn1Object;
+var
+  LContentsElements: IAsn1EncodableVector;
+begin
+  LContentsElements := ReadVector();
+  Result := TAsn1TaggedObject.CreateConstructedIL(ATagClass, ATagNo, LContentsElements);
+end;
+
+function TAsn1StreamParser.ReadVector(): IAsn1EncodableVector;
+var
+  LTagHdr: Int32;
+  LObj: IAsn1Convertible;
+  LV: TAsn1EncodableVector;
+begin
+  LTagHdr := FIn.ReadByte();
+  if LTagHdr < 0 then
+  begin
+    Result := TAsn1EncodableVector.Create(0);
+    Exit;
+  end;
+
+  LV := TAsn1EncodableVector.Create();
+  try
+    repeat
+      LObj := ImplParseObject(LTagHdr);
+      LV.Add(LObj.ToAsn1Object());
+      LTagHdr := FIn.ReadByte();
+    until LTagHdr < 0;
+    Result := LV;
+    LV := nil; // Don't free, interface owns it
+  finally
+    if LV <> nil then
+      LV.Free;
+  end;
+end;
+
+function TAsn1StreamParser.ParseObject(AUnivTagNo: Int32): IAsn1Convertible;
+var
+  LTagHdr: Int32;
+begin
+  if (AUnivTagNo < 0) or (AUnivTagNo > 30) then
+    raise EArgumentCryptoLibException.CreateFmt('invalid universal tag number: %d', [AUnivTagNo]);
+
+  LTagHdr := FIn.ReadByte();
+  if LTagHdr < 0 then
+  begin
+    Result := nil;
+    Exit;
+  end;
+
+  if ((LTagHdr and not TAsn1Tags.Constructed) <> AUnivTagNo) then
+    raise EIOCryptoLibException.CreateFmt('unexpected identifier encountered: %d', [LTagHdr]);
+
+  Result := ImplParseObject(LTagHdr);
+end;
+
+function TAsn1StreamParser.ParseTaggedObject(): IAsn1TaggedObjectParser;
+var
+  LTagHdr, LTagClass: Int32;
+  LResult: IAsn1Convertible;
+begin
+  LTagHdr := FIn.ReadByte();
+  if LTagHdr < 0 then
+  begin
+    Result := nil;
+    Exit;
+  end;
+
+  LTagClass := LTagHdr and TAsn1Tags.Private;
+  if LTagClass = 0 then
+    raise EAsn1CryptoLibException.Create('no tagged object found');
+
+  LResult := ImplParseObject(LTagHdr);
+  Result := LResult as IAsn1TaggedObjectParser;
+end;
+
+{ TBerBitStringParser }
+
+constructor TBerBitStringParser.Create(const AParser: IAsn1StreamParser);
+begin
+  inherited Create;
+  FParser := AParser;
+  FBitStream := nil;
+end;
+
+function TBerBitStringParser.GetBitStream(): TStream;
+begin
+  FBitStream := TAsn1ConstructedBitStream.Create(FParser, False);
+  Result := FBitStream;
+end;
+
+function TBerBitStringParser.GetOctetStream(): TStream;
+begin
+  FBitStream := TAsn1ConstructedBitStream.Create(FParser, True);
+  Result := FBitStream;
+end;
+
+function TBerBitStringParser.GetPadBits(): Int32;
+begin
+  Result := FBitStream.PadBits;
+end;
+
+
+function TBerBitStringParser.ToAsn1Object(): IAsn1Object;
+begin
+  try
+    Result := Parse(FParser);
+  except
+    on E: EIOCryptoLibException do
+      raise EAsn1ParsingCryptoLibException.Create('IOException converting stream to byte array: ' + E.Message);
+  end;
+end;
+
+class function TBerBitStringParser.Parse(const ASp: IAsn1StreamParser): IBerBitString;
+var
+  LBitStream: TAsn1ConstructedBitStream;
+  LData: TCryptoLibByteArray;
+  LPadBits: Int32;
+begin
+  LBitStream := TAsn1ConstructedBitStream.Create(ASp, False);
+  try
+    LData := TStreamUtilities.ReadAll(LBitStream);
+    LPadBits := LBitStream.PadBits;
+    Result := TBerBitString.Create(LData, LPadBits);
+  finally
+    LBitStream.Free;
+  end;
+end;
+
+{ TBerOctetStringParser }
+
+constructor TBerOctetStringParser.Create(const AParser: IAsn1StreamParser);
+begin
+  inherited Create;
+  FParser := AParser;
+end;
+
+function TBerOctetStringParser.GetOctetStream(): TStream;
+begin
+  Result := TAsn1ConstructedOctetStream.Create(FParser);
+end;
+
+function TBerOctetStringParser.ToAsn1Object(): IAsn1Object;
+begin
+  try
+    Result := Parse(FParser);
+  except
+    on E: EIOCryptoLibException do
+      raise EAsn1ParsingCryptoLibException.Create('IOException converting stream to byte array: ' + E.Message);
+  end;
+end;
+
+class function TBerOctetStringParser.Parse(const ASp: IAsn1StreamParser): IBerOctetString;
+var
+  LOctetStream: TAsn1ConstructedOctetStream;
+begin
+  LOctetStream := TAsn1ConstructedOctetStream.Create(ASp);
+  try
+    Result := TBerOctetString.Create(TStreamUtilities.ReadAll(LOctetStream));
+  finally
+    LOctetStream.Free;
+  end;
+end;
+
+{ TDerOctetStringParser }
+
+constructor TDerOctetStringParser.Create(const AStream: TAsn1DefiniteLengthInputStream);
+begin
+  inherited Create;
+  FStream := AStream;
+end;
+
+destructor TDerOctetStringParser.Destroy;
+begin
+  // Parser OWNS the stream and always frees it
+  if FStream <> nil then
+  begin
+    FStream.Free;
+    FStream := nil;
+  end;
+  inherited Destroy;
+end;
+
+function TDerOctetStringParser.GetOctetStream(): TStream;
+begin
+  // Transfers ownership to caller - caller MUST free the stream
+  Result := FStream;
+  FStream := nil;  // Transfer ownership, destructor won't free
+end;
+
+function TDerOctetStringParser.ToAsn1Object(): IAsn1Object;
+begin
+  try
+    Result := TDerOctetString.WithContents(FStream.ToArray());
+  except
+    on E: EIOCryptoLibException do
+      raise EInvalidOperationCryptoLibException.Create('IOException converting stream to byte array: ' + E.Message);
+  end;
+end;
+
+{ TDLBitStringParser }
+
+constructor TDLBitStringParser.Create(const AStream: TAsn1DefiniteLengthInputStream);
+begin
+  inherited Create;
+  FStream := AStream;
+  FPadBits := 0;
+end;
+
+destructor TDLBitStringParser.Destroy;
+begin
+  // Parser OWNS the stream and always frees it
+  if FStream <> nil then
+  begin
+    FStream.Free;
+    FStream := nil;
+  end;
+  inherited Destroy;
+end;
+
+function TDLBitStringParser.GetBitStreamInternal(AOctetAligned: Boolean): TStream;
+var
+  LLength: Int32;
+begin
+  LLength := FStream.Remaining;
+  if LLength < 1 then
+    raise EInvalidOperationCryptoLibException.Create('content octets cannot be empty');
+
+  FPadBits := FStream.ReadByte();
+  if FPadBits > 0 then
+  begin
+    if LLength < 2 then
+      raise EInvalidOperationCryptoLibException.Create('zero length data with non-zero pad bits');
+    if FPadBits > 7 then
+      raise EInvalidOperationCryptoLibException.Create('pad bits cannot be greater than 7 or less than 0');
+    if AOctetAligned then
+      raise EIOCryptoLibException.CreateFmt('expected octet-aligned bitstring, but found padBits: %d', [FPadBits]);
+  end;
+
+  // Transfers ownership to caller - caller MUST free the stream
+  Result := FStream;
+  FStream := nil;  // Transfer ownership, destructor won't free
+end;
+
+function TDLBitStringParser.GetBitStream(): TStream;
+begin
+  Result := GetBitStreamInternal(False);
+end;
+
+function TDLBitStringParser.GetOctetStream(): TStream;
+begin
+  Result := GetBitStreamInternal(True);
+end;
+
+function TDLBitStringParser.GetPadBits(): Int32;
+begin
+  Result := FPadBits;
+end;
+
+function TDLBitStringParser.ToAsn1Object(): IAsn1Object;
+begin
+  try
+    Result := TDerBitString.CreatePrimitive(FStream.ToArray());
+  except
+    on E: EIOCryptoLibException do
+      raise EAsn1ParsingCryptoLibException.Create('IOException converting stream to byte array: ' + E.Message);
+  end;
+end;
+
+{ TDerSequenceParser }
+
+constructor TDerSequenceParser.Create(const AParser: IAsn1StreamParser);
+begin
+  inherited Create;
+  FParser := AParser;
+end;
+
+function TDerSequenceParser.ReadObject(): IAsn1Convertible;
+begin
+  Result := FParser.ReadObject();
+end;
+
+function TDerSequenceParser.ToAsn1Object(): IAsn1Object;
+begin
+  Result := TDLSequence.FromVector(FParser.ReadVector());
+end;
+
+{ TDerSetParser }
+
+constructor TDerSetParser.Create(const AParser: IAsn1StreamParser);
+begin
+  inherited Create;
+  FParser := AParser;
+end;
+
+function TDerSetParser.ReadObject(): IAsn1Convertible;
+begin
+  Result := FParser.ReadObject();
+end;
+
+function TDerSetParser.ToAsn1Object(): IAsn1Object;
+begin
+  Result := TDLSet.FromVector(FParser.ReadVector());
+end;
+
+{ TBerSequenceParser }
+
+constructor TBerSequenceParser.Create(const AParser: IAsn1StreamParser);
+begin
+  inherited Create;
+  FParser := AParser;
+end;
+
+function TBerSequenceParser.ReadObject(): IAsn1Convertible;
+begin
+  Result := FParser.ReadObject();
+end;
+
+function TBerSequenceParser.ToAsn1Object(): IAsn1Object;
+begin
+  Result := Parse(FParser);
+end;
+
+class function TBerSequenceParser.Parse(const ASp: IAsn1StreamParser): IBerSequence;
+begin
+  Result := TBerSequence.FromVector(ASp.ReadVector());
+end;
+
+{ TBerSetParser }
+
+constructor TBerSetParser.Create(const AParser: IAsn1StreamParser);
+begin
+  inherited Create;
+  FParser := AParser;
+end;
+
+function TBerSetParser.ReadObject(): IAsn1Convertible;
+begin
+  Result := FParser.ReadObject();
+end;
+
+function TBerSetParser.ToAsn1Object(): IAsn1Object;
+begin
+  Result := Parse(FParser);
+end;
+
+class function TBerSetParser.Parse(const ASp: IAsn1StreamParser): IBerSet;
+begin
+  Result := TBerSet.FromVector(ASp.ReadVector());
+end;
+
+{ TDerExternalParser }
+
+constructor TDerExternalParser.Create(const AParser: IAsn1StreamParser);
+begin
+  inherited Create;
+  FParser := AParser;
+end;
+
+function TDerExternalParser.ReadObject(): IAsn1Convertible;
+begin
+  Result := FParser.ReadObject();
+end;
+
+function TDerExternalParser.ToAsn1Object(): IAsn1Object;
+begin
+  Result := Parse(FParser);
+end;
+
+class function TDerExternalParser.Parse(const ASp: IAsn1StreamParser): IDerExternal;
+begin
+  Result := TDLExternal.Create(TDLSequence.FromVector(ASp.ReadVector()));
+end;
+
+{ TBerTaggedObjectParser }
+
+constructor TBerTaggedObjectParser.Create(ATagClass, ATagNo: Int32; const AParser: IAsn1StreamParser);
+begin
+  inherited Create;
+  FTagClass := ATagClass;
+  FTagNo := ATagNo;
+  FParser := AParser;
+end;
+
+function TBerTaggedObjectParser.GetTagClass(): Int32;
+begin
+  Result := FTagClass;
+end;
+
+function TBerTaggedObjectParser.GetTagNo(): Int32;
+begin
+  Result := FTagNo;
+end;
+
+function TBerTaggedObjectParser.GetIsConstructed(): Boolean;
+begin
+  Result := True; // BER tagged objects are always constructed
+end;
+
+function TBerTaggedObjectParser.HasContextTag(ATagNo: Int32): Boolean;
+begin
+  Result := (FTagClass = TAsn1Tags.ContextSpecific) and (FTagNo = ATagNo);
+end;
+
+function TBerTaggedObjectParser.HasTag(ATagClass, ATagNo: Int32): Boolean;
+begin
+  Result := (FTagClass = ATagClass) and (FTagNo = ATagNo);
+end;
+
+function TBerTaggedObjectParser.ParseBaseUniversal(ADeclaredExplicit: Boolean; ABaseTagNo: Int32): IAsn1Convertible;
+begin
+  if ADeclaredExplicit then
+    Result := FParser.ParseObject(ABaseTagNo)
+  else
+    Result := FParser.ParseImplicitConstructedIL(ABaseTagNo);
+end;
+
+function TBerTaggedObjectParser.ParseExplicitBaseObject(): IAsn1Convertible;
+begin
+  Result := FParser.ReadObject();
+end;
+
+function TBerTaggedObjectParser.ParseExplicitBaseTagged(): IAsn1TaggedObjectParser;
+begin
+  Result := FParser.ParseTaggedObject();
+end;
+
+function TBerTaggedObjectParser.ParseImplicitBaseTagged(ABaseTagClass, ABaseTagNo: Int32): IAsn1TaggedObjectParser;
+begin
+  Result := TBerTaggedObjectParser.Create(ABaseTagClass, ABaseTagNo, FParser);
+end;
+
+function TBerTaggedObjectParser.ToAsn1Object(): IAsn1Object;
+begin
+  try
+    Result := FParser.LoadTaggedIL(FTagClass, FTagNo);
+  except
+    on E: EIOCryptoLibException do
+      raise EAsn1ParsingCryptoLibException.Create(E.Message);
+  end;
+end;
+
+{ TDLTaggedObjectParser }
+
+constructor TDLTaggedObjectParser.Create(ATagClass, ATagNo: Int32; AConstructed: Boolean;
+  const AParser: IAsn1StreamParser);
+begin
+  inherited Create(ATagClass, ATagNo, AParser);
+  FConstructed := AConstructed;
+end;
+
+function TDLTaggedObjectParser.ParseBaseUniversal(ADeclaredExplicit: Boolean; ABaseTagNo: Int32): IAsn1Convertible;
+var
+  LSp: IAsn1StreamParser;
+begin
+  if ADeclaredExplicit then
+  begin
+    LSp := CheckConstructed();
+    Result := LSp.ParseObject(ABaseTagNo);
+  end
+  else
+  begin
+    if FConstructed then
+      Result := FParser.ParseImplicitConstructedDL(ABaseTagNo)
+    else
+      Result := FParser.ParseImplicitPrimitive(ABaseTagNo);
+  end;
+end;
+
+function TDLTaggedObjectParser.ParseExplicitBaseObject(): IAsn1Convertible;
+var
+  LSp: IAsn1StreamParser;
+begin
+  LSp := CheckConstructed();
+  Result := LSp.ReadObject();
+end;
+
+function TDLTaggedObjectParser.ParseExplicitBaseTagged(): IAsn1TaggedObjectParser;
+var
+  LSp: IAsn1StreamParser;
+begin
+  LSp := CheckConstructed();
+  Result := LSp.ParseTaggedObject();
+end;
+
+function TDLTaggedObjectParser.ParseImplicitBaseTagged(ABaseTagClass, ABaseTagNo: Int32): IAsn1TaggedObjectParser;
+begin
+  Result := TDLTaggedObjectParser.Create(ABaseTagClass, ABaseTagNo, FConstructed, FParser);
+end;
+
+function TDLTaggedObjectParser.ToAsn1Object(): IAsn1Object;
+begin
+  try
+    Result := FParser.LoadTaggedDL(FTagClass, FTagNo, FConstructed);
+  except
+    on E: EIOCryptoLibException do
+      raise EAsn1ParsingCryptoLibException.Create(E.Message);
+  end;
+end;
+
+function TDLTaggedObjectParser.GetIsConstructed(): Boolean;
+begin
+  Result := FConstructed;
+end;
+
+function TDLTaggedObjectParser.CheckConstructed(): IAsn1StreamParser;
+begin
+  if not FConstructed then
+    raise EIOCryptoLibException.Create('Explicit tags must be constructed (see X.690 8.14.2)');
+  Result := FParser;
+end;
+
+end.

+ 8 - 1
CryptoLib/src/Asn1/ClpAsn1Streams.pas

@@ -25,7 +25,12 @@ uses
   Classes,
   Math,
   SysUtils,
+  ClpIAsn1Core,
+  ClpIAsn1Encodings,
   ClpIAsn1Objects,
+  ClpIAsn1Parsers,
+  ClpAsn1Encodings,
+  ClpAsn1Tags,
   ClpBitUtilities,
   ClpPlatformUtilities,
   ClpCryptoLibTypes,
@@ -485,7 +490,9 @@ type
 implementation
 
 uses
-  ClpAsn1Objects;
+  ClpAsn1Objects,
+  ClpAsn1Parsers,
+  ClpAsn1Core;
 
 { TAsn1LimitedInputStream }
 

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

@@ -0,0 +1,84 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpAsn1Tags;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+type
+  /// <summary>
+  /// ASN.1 tags constants.
+  /// </summary>
+  TAsn1Tags = class sealed(TObject)
+  public
+    // 0x00: Reserved for use by the encoding rules
+    const
+      Boolean = $01;
+      Integer = $02;
+      BitString = $03;
+      OctetString = $04;
+      Null = $05;
+      ObjectIdentifier = $06;
+      ObjectDescriptor = $07;
+      &External = $08;
+      Real = $09;
+      Enumerated = $0A;
+      EmbeddedPdv = $0B;
+      Utf8String = $0C;
+      RelativeOid = $0D;
+      Time = $0E;
+      // 0x0f: Reserved for future editions of this Recommendation | International Standard
+      Sequence = $10;
+      SequenceOf = $10; // for completeness
+      &Set = $11;
+      SetOf = $11; // for completeness
+      NumericString = $12;
+      PrintableString = $13;
+      T61String = $14;
+      VideotexString = $15;
+      IA5String = $16;
+      UtcTime = $17;
+      GeneralizedTime = $18;
+      GraphicString = $19;
+      VisibleString = $1A;
+      GeneralString = $1B;
+      UniversalString = $1C;
+      UnrestrictedString = $1D;
+      BmpString = $1E;
+      Date = $1F;
+      TimeOfDay = $20;
+      DateTime = $21;
+      Duration = $22;
+      ObjectIdentifierIri = $23;
+      RelativeOidIri = $24;
+      // 0x25..: Reserved for addenda to this Recommendation | International Standard
+
+      Constructed = $20;
+
+      Universal = $00;
+      Application = $40;
+      ContextSpecific = $80;
+      &Private = $C0;
+
+      Flags = $E0;
+  end;
+
+implementation
+
+end.

+ 3 - 0
CryptoLib/src/Asn1/ClpAsn1Utilities.pas

@@ -24,7 +24,10 @@ interface
 uses
   SysUtils,
   TypInfo,
+  ClpAsn1Tags,
   ClpIAsn1Objects,
+  ClpIAsn1Core,
+  ClpIAsn1Parsers,
   ClpPlatformUtilities,
   ClpCryptoLibTypes;
 

+ 0 - 1
CryptoLib/src/Asn1/Eac/ClpEacObjectIdentifiers.pas

@@ -22,7 +22,6 @@ unit ClpEacObjectIdentifiers;
 interface
 
 uses
-  ClpAsn1Objects,
   ClpBsiObjectIdentifiers,
   ClpIAsn1Objects;
 

+ 3 - 1
CryptoLib/src/Asn1/Pkcs/ClpPkcsAsn1Objects.pas

@@ -23,10 +23,12 @@ interface
 
 uses
   SysUtils,
-  Classes,
   ClpBigInteger,
   ClpAsn1Objects,
   ClpIAsn1Objects,
+  ClpAsn1Core,
+  ClpIAsn1Core,
+  ClpAsn1Tags,
   ClpIPkcsAsn1Objects,
   ClpX509Asn1Objects,
   ClpIX509Asn1Objects,

+ 2 - 0
CryptoLib/src/Asn1/Sec/ClpSecAsn1Objects.pas

@@ -27,6 +27,8 @@ uses
   ClpBigIntegers,
   ClpAsn1Objects,
   ClpIAsn1Objects,
+  ClpAsn1Core,
+  ClpIAsn1Core,
   ClpISecAsn1Objects,
   ClpCryptoLibTypes,
   ClpAsn1Utilities;

+ 3 - 3
CryptoLib/src/Asn1/X500/Style/ClpIetfUtilities.pas

@@ -23,12 +23,12 @@ interface
 
 uses
   SysUtils,
-  Classes,
-  ClpAsn1Objects,
+  ClpAsn1Core,
+  ClpIAsn1Core,
   ClpIAsn1Objects,
   ClpCryptoLibTypes,
   ClpStringUtilities,
-  ClpPlatformUtilities,
+
   ClpEncoders;
 
 type

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

@@ -25,6 +25,8 @@ uses
   SysUtils,
   ClpAsn1Objects,
   ClpIAsn1Objects,
+  ClpAsn1Core,
+  ClpIAsn1Core,
   ClpIAlgorithmIdentifier,
   ClpCryptoLibTypes;
 

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

@@ -25,6 +25,8 @@ uses
   SysUtils,
   ClpAsn1Objects,
   ClpIAsn1Objects,
+  ClpAsn1Core,
+  ClpIAsn1Core,
   ClpIAlgorithmIdentifier,
   ClpAlgorithmIdentifier,
   ClpIDigestInfo,

+ 2 - 0
CryptoLib/src/Asn1/X509/ClpDsaParameter.pas

@@ -25,6 +25,8 @@ uses
   ClpIDsaParameter,
   ClpAsn1Objects,
   ClpIAsn1Objects,
+  ClpAsn1Core,
+  ClpIAsn1Core,
   ClpBigInteger,
   ClpCryptoLibTypes;
 

+ 0 - 1
CryptoLib/src/Asn1/X509/ClpRfc5280Asn1Utilities.pas

@@ -22,7 +22,6 @@ unit ClpRfc5280Asn1Utilities;
 interface
 
 uses
-  SysUtils,
   ClpDateTimeUtilities,
   ClpAsn1Objects,
   ClpIAsn1Objects;

+ 2 - 0
CryptoLib/src/Asn1/X509/ClpV2AttributeCertificateInfoGenerator.pas

@@ -25,6 +25,8 @@ uses
   SysUtils,
   ClpAsn1Objects,
   ClpIAsn1Objects,
+  ClpAsn1Core,
+  ClpIAsn1Core,
   ClpIX509Asn1Objects,
   ClpX509Asn1Objects,
   ClpCryptoLibTypes;

+ 2 - 0
CryptoLib/src/Asn1/X509/ClpV3TbsCertificateGenerator.pas

@@ -25,6 +25,8 @@ uses
   SysUtils,
   ClpAsn1Objects,
   ClpIAsn1Objects,
+  ClpAsn1Core,
+  ClpIAsn1Core,
   ClpIX509Asn1Objects,
   ClpIX509Extension,
   ClpX509Asn1Objects,

+ 3 - 2
CryptoLib/src/Asn1/X509/ClpX509Asn1Objects.pas

@@ -27,19 +27,20 @@ uses
   Classes,
   Generics.Collections,
   SyncObjs,
+  ClpAsn1Tags,
   ClpAsn1Objects,
   ClpIAsn1Objects,
+  ClpAsn1Core,
+  ClpIAsn1Core,
   ClpIX509Asn1Objects,
   ClpIX509Extension,
   ClpX509Extension,
   ClpIX509NameEntryConverter,
-  ClpX509NameEntryConverter,
   ClpIX509NameTokenizer,
   ClpX509NameTokenizer,
   ClpX509ObjectIdentifiers,
   ClpPkcsObjectIdentifiers,
   ClpBigInteger,
-  ClpBigIntegers,
   ClpCryptoLibTypes,
   ClpArrayUtilities,
   ClpAsn1Utilities,

+ 1 - 2
CryptoLib/src/Asn1/X509/ClpX509DefaultEntryConverter.pas

@@ -25,11 +25,10 @@ uses
   SysUtils,
   ClpAsn1Objects,
   ClpIAsn1Objects,
+  ClpIAsn1Core,
   ClpIX509NameEntryConverter,
   ClpX509NameEntryConverter,
   ClpX509Asn1Objects,
-  ClpX509ObjectIdentifiers,
-  ClpPkcsObjectIdentifiers,
   ClpCryptoLibTypes;
 
 type

+ 1 - 0
CryptoLib/src/Asn1/X509/ClpX509Extension.pas

@@ -23,6 +23,7 @@ interface
 
 uses
   SysUtils,
+  ClpIAsn1Core,
   ClpAsn1Objects,
   ClpIAsn1Objects,
   ClpIX509Extension,

+ 1 - 1
CryptoLib/src/Asn1/X509/ClpX509ExtensionUtilities.pas

@@ -23,13 +23,13 @@ interface
 
 uses
   SysUtils,
+  ClpIAsn1Core,
   ClpAsn1Objects,
   ClpIAsn1Objects,
   ClpIX509Asn1Objects,
   ClpX509Asn1Objects,
   ClpOiwObjectIdentifiers,
   ClpDigestUtilities,
-  ClpBigInteger,
   ClpCryptoLibTypes,
   ClpArrayUtilities;
 

+ 2 - 0
CryptoLib/src/Asn1/X509/ClpX509ExtensionsGenerator.pas

@@ -26,6 +26,8 @@ uses
   Generics.Collections,
   ClpAsn1Objects,
   ClpIAsn1Objects,
+  ClpAsn1Core,
+  ClpIAsn1Core,
   ClpIX509ExtensionsGenerator,
   ClpIX509Asn1Objects,
   ClpIX509Extension,

+ 1 - 0
CryptoLib/src/Asn1/X509/ClpX509NameEntryConverter.pas

@@ -25,6 +25,7 @@ uses
   SysUtils,
   ClpAsn1Objects,
   ClpIAsn1Objects,
+  ClpIAsn1Core,
   ClpIX509NameEntryConverter,
   ClpEncoders,
   ClpCryptoLibTypes;

+ 1 - 0
CryptoLib/src/Asn1/X509/ClpX509SignatureUtilities.pas

@@ -24,6 +24,7 @@ interface
 uses
   SysUtils,
   Generics.Collections,
+  ClpIAsn1Core,
   ClpAsn1Objects,
   ClpIAsn1Objects,
   ClpIX509Asn1Objects,

+ 2 - 0
CryptoLib/src/Asn1/X9/ClpDHDomainParameters.pas

@@ -27,6 +27,8 @@ uses
   ClpDHValidationParams,
   ClpAsn1Objects,
   ClpIAsn1Objects,
+  ClpAsn1Core,
+  ClpIAsn1Core,
   ClpAsn1Utilities,
   ClpCryptoLibTypes;
 

+ 2 - 1
CryptoLib/src/Asn1/X9/ClpDHValidationParams.pas

@@ -26,7 +26,8 @@ uses
   ClpIDHValidationParams,
   ClpAsn1Objects,
   ClpIAsn1Objects,
-  ClpBigInteger,
+  ClpAsn1Core,
+  ClpIAsn1Core,
   ClpCryptoLibTypes;
 
 resourcestring

+ 2 - 4
CryptoLib/src/Asn1/X9/ClpX9Asn1Objects.pas

@@ -25,13 +25,11 @@ uses
   SysUtils,
   ClpAsn1Objects,
   ClpIAsn1Objects,
+  ClpAsn1Core,
+  ClpIAsn1Core,
   ClpIX9Asn1Objects,
   ClpIX9ECParameters,
-  ClpX9ObjectIdentifiers,
-  ClpX9ECC,
   ClpX9ECParameters,
-  ClpBigInteger,
-  ClpBigIntegers,
   ClpCryptoLibTypes,
   ClpAsn1Utilities;
 

+ 2 - 0
CryptoLib/src/Asn1/X9/ClpX9ECC.pas

@@ -25,6 +25,8 @@ uses
   ClpECC,
   ClpIECC,
   ClpIX9ECC,
+  ClpAsn1Core,
+  ClpIAsn1Core,
   ClpCryptoLibTypes,
   ClpECAlgorithms,
   ClpBigInteger,

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

@@ -27,6 +27,8 @@ uses
   ClpBigInteger,
   ClpIPolynomialExtensionField,
   ClpIAsn1Objects,
+  ClpAsn1Core,
+  ClpIAsn1Core,
   ClpIECC,
   ClpECAlgorithms,
   ClpX9ECC,

+ 0 - 1
CryptoLib/src/Crypto/Ciphers/ClpIESCipher.pas

@@ -46,7 +46,6 @@ uses
   ClpKeyEncoder,
   ClpIKeyEncoder,
   ClpISecureRandom,
-  ClpSecureRandom,
   ClpCryptoLibTypes;
 
 resourcestring

+ 1 - 2
CryptoLib/src/Crypto/Encodings/ClpOaepEncoding.pas

@@ -32,8 +32,7 @@ uses
   ClpIOaepEncoding,
   ClpISecureRandom,
   ClpSecureRandom,
-  ClpCryptoLibTypes,
-  ClpConverters;
+  ClpCryptoLibTypes;
 
 resourcestring
   SInputDataTooLong = 'Input data too long';

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

@@ -26,7 +26,6 @@ uses
   ClpBigInteger,
   ClpICipherParameters,
   ClpIRsa,
-  ClpIRsaCoreEngine,
   ClpRsaCoreEngine,
   ClpIAsymmetricBlockCipher,
   ClpIRsaEngine,

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

@@ -36,7 +36,6 @@ uses
   ClpAsymmetricCipherKeyPair,
   ClpIAsymmetricCipherKeyPairGenerator,
   ClpIRsaKeyPairGenerator,
-  ClpISecureRandom,
   ClpECCompUtilities,
   ClpCryptoLibTypes;
 

+ 1 - 2
CryptoLib/src/Crypto/Macs/ClpMacUtilities.pas

@@ -39,8 +39,7 @@ uses
   ClpPkcsObjectIdentifiers,
   ClpRosstandartObjectIdentifiers,
   ClpHMac,
-  ClpStringUtilities,
-  ClpPlatformUtilities;
+  ClpStringUtilities;
 
 resourcestring
   SOidNil = 'OID Cannot be Nil';

+ 1 - 2
CryptoLib/src/Crypto/Operators/ClpAsn1DigestFactory.pas

@@ -30,8 +30,7 @@ uses
   ClpX509Asn1Objects,
   ClpIAsn1Objects,
   ClpDigestUtilities,
-  ClpDefaultDigestCalculator,
-  ClpCryptoLibTypes;
+  ClpDefaultDigestCalculator;
 
 type
   /// <summary>

+ 0 - 1
CryptoLib/src/Crypto/Operators/ClpAsn1SignatureFactory.pas

@@ -23,7 +23,6 @@ interface
 
 uses
   ClpISignatureFactory,
-  ClpIAsn1Objects,
   ClpIX509Asn1Objects,
   ClpIAsymmetricKeyParameter,
   ClpISecureRandom,

+ 0 - 1
CryptoLib/src/Crypto/Operators/ClpAsn1VerifierFactory.pas

@@ -23,7 +23,6 @@ interface
 
 uses
   ClpIVerifierFactory,
-  ClpIAsn1Objects,
   ClpIX509Asn1Objects,
   ClpIAsymmetricKeyParameter,
   ClpIVerifier,

+ 0 - 1
CryptoLib/src/Crypto/Operators/ClpAsn1VerifierFactoryProvider.pas

@@ -25,7 +25,6 @@ uses
   SysUtils,
   ClpIVerifierFactoryProvider,
   ClpIVerifierFactory,
-  ClpIAsn1Objects,
   ClpIX509Asn1Objects,
   ClpIAsymmetricKeyParameter,
   ClpAsn1VerifierFactory,

+ 1 - 3
CryptoLib/src/Crypto/Parameters/ClpECDomainParameters.pas

@@ -31,9 +31,7 @@ uses
   ClpIX9ECParameters,
   ClpIAsn1Objects,
   ClpIX9Asn1Objects,
-  ClpX9Asn1Objects,
-  ClpX9ECParameters,
-  ClpIECNamedDomainParameters;
+  ClpX9ECParameters;
 
 resourcestring
   SCurveNil = 'Curve Cannot be Nil';

+ 0 - 2
CryptoLib/src/Crypto/Parameters/ClpECKeyParameters.pas

@@ -22,9 +22,7 @@ unit ClpECKeyParameters;
 interface
 
 uses
-
   SysUtils,
-  ClpECGost3410NamedCurves,
   ClpIECKeyParameters,
   ClpIECDomainParameters,
   ClpIECKeyGenerationParameters,

+ 0 - 1
CryptoLib/src/Crypto/Parameters/ClpECPublicKeyParameters.pas

@@ -23,7 +23,6 @@ interface
 
 uses
   ClpCryptoLibTypes,
-  ClpBigInteger,
   ClpIECC,
   ClpIECPublicKeyParameters,
   ClpIECDomainParameters,

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

@@ -31,8 +31,6 @@ uses
   ClpIEd25519PublicKeyParameters,
   ClpEd25519PublicKeyParameters,
   ClpArrayUtilities,
-  ClpAsn1Objects,
-  ClpStreams,
   ClpStreamUtilities,
   ClpCryptoLibTypes;
 

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

@@ -27,8 +27,6 @@ uses
   ClpAsymmetricKeyParameter,
   ClpIEd25519PublicKeyParameters,
   ClpArrayUtilities,
-  ClpAsn1Objects,
-  ClpStreams,
   ClpStreamUtilities,
   ClpCryptoLibTypes;
 

+ 1 - 2
CryptoLib/src/Crypto/Parameters/ClpParameterUtilities.pas

@@ -28,8 +28,8 @@ uses
   ClpCollectionUtilities,
   ClpCryptoLibComparers,
   ClpCryptoLibTypes,
-  ClpCryptoProObjectIdentifiers,
   ClpIAsn1Objects,
+  ClpIAsn1Core,
   ClpIKeyParameter,
   ClpICipherParameters,
   ClpIParametersWithRandom,
@@ -37,7 +37,6 @@ uses
   ClpKeyParameter,
   ClpMiscObjectIdentifiers,
   ClpNistObjectIdentifiers,
-  ClpOiwObjectIdentifiers,
   ClpParametersWithRandom,
   ClpParametersWithIV,
   ClpSecureRandom;

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

@@ -30,8 +30,6 @@ uses
   ClpIX25519PublicKeyParameters,
   ClpX25519PublicKeyParameters,
   ClpArrayUtilities,
-  ClpAsn1Objects,
-  ClpStreams,
   ClpStreamUtilities,
   ClpCryptoLibTypes;
 

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

@@ -27,8 +27,6 @@ uses
   ClpAsymmetricKeyParameter,
   ClpIX25519PublicKeyParameters,
   ClpArrayUtilities,
-  ClpAsn1Objects,
-  ClpStreams,
   ClpStreamUtilities,
   ClpCryptoLibTypes;
 

+ 0 - 2
CryptoLib/src/Crypto/Parsers/ClpECIESPublicKeyParser.pas

@@ -23,13 +23,11 @@ interface
 
 uses
   Classes,
-  ClpAsn1Objects,
   ClpIECDomainParameters,
   ClpECPublicKeyParameters,
   ClpIKeyParser,
   ClpIAsymmetricKeyParameter,
   ClpIECIESPublicKeyParser,
-  ClpStreams,
   ClpStreamUtilities,
   ClpCryptoLibTypes;
 

+ 1 - 2
CryptoLib/src/Crypto/Randoms/ClpSecureRandom.pas

@@ -39,8 +39,7 @@ uses
   ClpICryptoApiRandomGenerator,
   ClpDigestRandomGenerator,
   ClpIDigestRandomGenerator,
-  ClpISecureRandom,
-  ClpPlatformUtilities;
+  ClpISecureRandom;
 
 resourcestring
   SUnRecognisedPRNGAlgorithm = 'Unrecognised PRNG Algorithm: %s "algorithm"';

+ 0 - 1
CryptoLib/src/Crypto/Signers/ClpDsaDigestSigner.pas

@@ -27,7 +27,6 @@ uses
   ClpIDsa,
   ClpIDigest,
   ClpBigInteger,
-  ClpBigIntegers,
   ClpCryptoLibTypes,
   ClpParameterUtilities,
   ClpSignersEncodings,

+ 0 - 1
CryptoLib/src/Crypto/Signers/ClpECDsaSigner.pas

@@ -26,7 +26,6 @@ uses
   ClpBigInteger,
   ClpSecureRandom,
   ClpECAlgorithms,
-  ClpECC,
   ClpIECC,
   ClpIECPublicKeyParameters,
   ClpIECPrivateKeyParameters,

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

@@ -27,18 +27,14 @@ uses
   ClpCryptoLibComparers,
   ClpICipherParameters,
   ClpIAsymmetricKeyParameter,
-  ClpIParametersWithRandom,
   ClpParameterUtilities,
   ClpIDigest,
   ClpIRsa,
   ClpIAsymmetricBlockCipher,
   ClpISigner,
   ClpIRsaDigestSigner,
-  ClpIRsaCoreEngine,
   ClpRsaCoreEngine,
-  ClpIRsaBlindedEngine,
   ClpRsaBlindedEngine,
-  ClpIPkcs1Encoding,
   ClpPkcs1Encoding,
   ClpIX509Asn1Objects,
   ClpX509Asn1Objects,

+ 1 - 6
CryptoLib/src/Crypto/Signers/ClpSignerUtilities.pas

@@ -24,6 +24,7 @@ interface
 uses
   SysUtils,
   Generics.Collections,
+  ClpIAsn1Core,
   ClpAsn1Objects,
   ClpIX509Asn1Objects,
   ClpCollectionUtilities,
@@ -45,8 +46,6 @@ uses
   ClpEdECObjectIdentifiers,
   ClpParameterUtilities,
   ClpIAsymmetricKeyParameter,
-  ClpEd25519,
-  ClpIEd25519,
   ClpDsaSigner,
   ClpIDsaSigner,
   ClpECDsaSigner,
@@ -62,11 +61,8 @@ uses
   ClpIAsn1Objects,
   ClpSignersEncodings,
   ClpRsaDigestSigner,
-  ClpIRsaDigestSigner,
   ClpPssSigner,
-  ClpIPssSigner,
   ClpGenericSigner,
-  ClpIGenericSigner,
   ClpX931Signer,
   ClpRsaBlindedEngine,
   ClpIRsaBlindedEngine,
@@ -75,7 +71,6 @@ uses
   ClpPkcsObjectIdentifiers,
   ClpStringUtilities,
   ClpCryptoLibTypes,
-  ClpPlatformUtilities,
   ClpPkcsAsn1Objects,
   ClpX509Asn1Objects;
 

+ 1 - 0
CryptoLib/src/Crypto/Signers/SignerEncodings/ClpSignersEncodings.pas

@@ -25,6 +25,7 @@ uses
   Math,
   ClpAsn1Objects,
   ClpBigInteger,
+  ClpAsn1Core,
   ClpISignersEncodings,
   ClpIAsn1Objects,
   ClpArrayUtilities,

+ 1 - 10
CryptoLib/src/Factories/ClpPrivateKeyFactory.pas

@@ -24,14 +24,12 @@ interface
 uses
   Classes,
   SysUtils,
+  ClpIAsn1Core,
   ClpAsn1Objects,
   ClpIAsn1Objects,
   ClpIPkcsAsn1Objects,
   ClpIX9Asn1Objects,
   ClpIAsymmetricKeyParameter,
-  ClpIRsaPrivateCrtKeyParameters,
-  ClpIDsaPrivateKeyParameters,
-  ClpIECPrivateKeyParameters,
   ClpRsaPrivateCrtKeyParameters,
   ClpDsaPrivateKeyParameters,
   ClpECPrivateKeyParameters,
@@ -41,15 +39,9 @@ uses
   ClpPkcsObjectIdentifiers,
   ClpX509ObjectIdentifiers,
   ClpX9ObjectIdentifiers,
-  ClpOiwObjectIdentifiers,
   ClpX9Asn1Objects,
-  ClpX9ECC,
-  ClpX9ECParameters,
   ClpIX9ECParameters,
   ClpPkcsAsn1Objects,
-  ClpX509Asn1Objects,
-  ClpECNamedCurveTable,
-  ClpECNamedDomainParameters,
   ClpIECDomainParameters,
   ClpIDsaParameters,
   ClpIDsaParameter,
@@ -57,7 +49,6 @@ uses
   ClpSecAsn1Objects,
   ClpISecAsn1Objects,
   ClpBigInteger,
-  ClpBigIntegers,
   ClpCryptoLibTypes;
 
 type

+ 0 - 8
CryptoLib/src/Factories/ClpPublicKeyFactory.pas

@@ -26,9 +26,6 @@ uses
   ClpIAsn1Objects,
   ClpIX509Asn1Objects,
   ClpIAsymmetricKeyParameter,
-  ClpIRsaKeyParameters,
-  ClpIDsaPublicKeyParameters,
-  ClpIECPublicKeyParameters,
   ClpRsaKeyParameters,
   ClpDsaPublicKeyParameters,
   ClpECPublicKeyParameters,
@@ -40,14 +37,9 @@ uses
   ClpOiwObjectIdentifiers,
   ClpX9Asn1Objects,
   ClpIX9Asn1Objects,
-  ClpX9ECC,
-  ClpX9ECParameters,
   ClpIX9ECParameters,
   ClpX509Asn1Objects,
-  ClpPkcsAsn1Objects,
   ClpAsn1Objects,
-  ClpECNamedCurveTable,
-  ClpECNamedDomainParameters,
   ClpIECC,
   ClpIECDomainParameters,
   ClpIDsaParameters,

+ 1 - 2
CryptoLib/src/GeneralUtilities/ClpCryptoLibComparers.pas

@@ -24,8 +24,7 @@ interface
 uses
   Generics.Defaults,
   ClpIAsn1Objects,
-  ClpStringUtilities,
-  ClpPlatformUtilities;
+  ClpStringUtilities;
 
 type
   /// <summary>

+ 0 - 1
CryptoLib/src/GeneralUtilities/ClpEnumUtilities.pas

@@ -25,7 +25,6 @@ uses
   SysUtils,
   TypInfo,
   ClpDateTimeUtilities,
-  ClpPlatformUtilities,
   ClpStringUtilities,
   ClpCryptoLibTypes;
 

+ 124 - 0
CryptoLib/src/Interfaces/Asn1/ClpIAsn1Core.pas

@@ -0,0 +1,124 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpIAsn1Core;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpCryptoLibTypes,
+  ClpIAsn1Encodings;
+
+type
+  IAsn1Object = interface; // forward (used by IAsn1Convertible)
+
+  /// <summary>
+  /// Interface for ASN.1 convertible objects.
+  /// </summary>
+  IAsn1Convertible = interface(IInterface)
+    ['{13104D9E-9DF1-4CCE-B48C-1ACC2AC362B1}']
+
+    function ToAsn1Object(): IAsn1Object;
+  end;
+
+  /// <summary>
+  /// Interface for ASN.1 encodable objects.
+  /// </summary>
+  IAsn1Encodable = interface(IAsn1Convertible)
+    ['{E6F78901-2345-6789-ABCD-EF0123456789}']
+
+    procedure EncodeTo(const AOutput: TStream); overload;
+    procedure EncodeTo(const AOutput: TStream; const AEncoding: String); overload;
+    function GetEncoded(): TCryptoLibByteArray; overload;
+    function GetEncoded(const AEncoding: String): TCryptoLibByteArray; overload;
+    function GetDerEncoded(): TCryptoLibByteArray;
+    function Equals(const AObj: IAsn1Convertible): Boolean; overload;
+    function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt; {$ENDIF DELPHI}
+  end;
+
+  /// <summary>
+  /// Interface for ASN.1 objects.
+  /// </summary>
+  IAsn1Object = interface(IAsn1Encodable)
+    ['{F7890123-4567-89AB-CDEF-0123456789AB}']
+
+    procedure EncodeTo(const AOutput: TStream); overload;
+    procedure EncodeTo(const AOutput: TStream; const AEncoding: String); overload;
+    function GetEncoded(const AEncoding: String; APreAlloc, APostAlloc: Int32): TCryptoLibByteArray; overload;
+    function Equals(const AOther: IAsn1Object): Boolean; overload;
+    function Asn1Equals(const AAsn1Object: IAsn1Object): Boolean;
+    function Asn1GetHashCode(): Int32;
+    function CallAsn1Equals(const AObj: IAsn1Object): Boolean;
+    function CallAsn1GetHashCode(): Int32;
+    /// <summary>
+    /// Get string representation of the object.
+    /// </summary>
+    function ToString(): String;
+    /// <summary>
+    /// Get encoding for the specified encoding type.
+    /// </summary>
+    function GetEncoding(AEncoding: Int32): IAsn1Encoding;
+    /// <summary>
+    /// Get encoding for the specified encoding type with implicit tagging.
+    /// </summary>
+    function GetEncodingImplicit(AEncoding, ATagClass, ATagNo: Int32): IAsn1Encoding;
+    /// <summary>
+    /// Get DER encoding.
+    /// </summary>
+    function GetEncodingDer(): IDerEncoding;
+    /// <summary>
+    /// Get DER encoding with implicit tagging.
+    /// </summary>
+    function GetEncodingDerImplicit(ATagClass, ATagNo: Int32): IDerEncoding;
+  end;
+
+  /// <summary>
+  /// Interface for ASN.1 encodable vector.
+  /// </summary>
+  IAsn1EncodableVector = interface(IInterface)
+    ['{A78E22EB-DB67-472E-A55F-CD710BCBDBFA}']
+
+    function GetCount(): Int32;
+    function GetItem(AIndex: Int32): IAsn1Encodable;
+
+    procedure Add(const AElement: IAsn1Encodable); overload;
+    procedure Add(const AElement1, AElement2: IAsn1Encodable); overload;
+    procedure Add(const AObjs: array of IAsn1Encodable); overload;
+    procedure AddOptional(const AElement: IAsn1Encodable); overload;
+    procedure AddOptional(const AElement1, AElement2: IAsn1Encodable); overload;
+    procedure AddOptional(const AElements: array of IAsn1Encodable); overload;
+    procedure AddOptionalTagged(AIsExplicit: Boolean; ATagNo: Int32;
+      const AObj: IAsn1Encodable); overload;
+    procedure AddOptionalTagged(AIsExplicit: Boolean; ATagClass, ATagNo: Int32;
+      const AObj: IAsn1Encodable); overload;
+    procedure AddAll(const AE: TCryptoLibGenericArray<IAsn1Encodable>); overload;
+    procedure AddAll(const AOther: IAsn1EncodableVector); overload;
+
+    function CopyElements(): TCryptoLibGenericArray<IAsn1Encodable>;
+    function TakeElements(): TCryptoLibGenericArray<IAsn1Encodable>;
+
+    property Items[AIndex: Int32]: IAsn1Encodable read GetItem; default;
+    property Count: Int32 read GetCount;
+  end;
+
+implementation
+
+end.
+

Некоторые файлы не были показаны из-за большого количества измененных файлов