3using System.Diagnostics.CodeAnalysis;
4using System.Formats.Asn1;
5using System.Globalization;
6using System.Reflection;
23 private static readonly SortedDictionary<string, int> oidsNotRecognized = [];
24 private static readonly SortedDictionary<string, int> oidsNotConfigured = [];
25 private static readonly SortedDictionary<string, int> algorithmsUsed = [];
26 private static readonly SortedDictionary<string, int> unrecognizedCurves = [];
27 private static Dictionary<string, ConstructorInfo>? objectConstructors =
null;
37 public static bool TryDecodeDerAs(UniversalTagNumber TagNumber,
byte[] Data, out
object? Value)
52 byte[] Data, out
object? Value)
60 byte Tag = (byte)TagNumber;
61 if (TagNumber == UniversalTagNumber.Sequence || TagNumber == UniversalTagNumber.Set)
64 Data = (
byte[])Data.Clone();
67 AsnReader Reader =
new(Data, AsnEncodingRules.DER);
91 AsnReader Reader =
new(Data, AsnEncodingRules.DER);
130 Asn1Tag Tag = Reader.PeekTag();
132 if (Tag.TagClass == TagClass.Universal)
134 switch (Tag.TagValue)
136 case (
int)UniversalTagNumber.EndOfContents:
140 case (
int)UniversalTagNumber.Boolean:
146 ReadOnlyMemory<byte> Section = Reader.ReadEncodedValue();
148 if (Section.Length == 3)
149 Value = Section.Span[^1] != 0;
151 Value = Reader.ReadBoolean();
155 case (
int)UniversalTagNumber.Integer:
156 case (
int)UniversalTagNumber.Enumerated:
157 Value = Reader.ReadInteger();
160 case (
int)UniversalTagNumber.BitString:
161 Value = Reader.ReadBitString(out
_);
164 case (
int)UniversalTagNumber.OctetString:
165 byte[] Bin = Reader.ReadOctetString();
167 if (Tag.IsConstructed)
186 case (
int)UniversalTagNumber.Null:
191 case (
int)UniversalTagNumber.ObjectIdentifier:
192 string Oid = Reader.ReadObjectIdentifier();
198 Client?.
Warning(
"OID not recognized: " + Oid);
204 case (
int)UniversalTagNumber.ObjectDescriptor:
205 case (
int)UniversalTagNumber.UTF8String:
206 case (
int)UniversalTagNumber.NumericString:
207 case (
int)UniversalTagNumber.PrintableString:
208 case (
int)UniversalTagNumber.TeletexString:
209 case (
int)UniversalTagNumber.VideotexString:
210 case (
int)UniversalTagNumber.IA5String:
211 case (
int)UniversalTagNumber.GraphicString:
212 case (
int)UniversalTagNumber.VisibleString:
213 case (
int)UniversalTagNumber.GeneralString:
214 case (
int)UniversalTagNumber.UniversalString:
215 case (
int)UniversalTagNumber.UnrestrictedCharacterString:
216 case (
int)UniversalTagNumber.BMPString:
217 Value = Reader.ReadCharacterString((UniversalTagNumber)Tag.TagValue);
220 case (
int)UniversalTagNumber.Real:
221 case (
int)UniversalTagNumber.RelativeObjectIdentifier:
222 case (
int)UniversalTagNumber.Time:
223 case (
int)UniversalTagNumber.Date:
224 case (
int)UniversalTagNumber.TimeOfDay:
225 case (
int)UniversalTagNumber.DateTime:
226 case (
int)UniversalTagNumber.Duration:
227 case (
int)UniversalTagNumber.ObjectIdentifierIRI:
228 case (
int)UniversalTagNumber.RelativeObjectIdentifierIRI:
229 Value = Reader.ReadEncodedValue();
232 case (
int)UniversalTagNumber.Sequence:
233 case (
int)UniversalTagNumber.External:
234 case (
int)UniversalTagNumber.Set:
235 case (
int)UniversalTagNumber.Embedded:
237 Section = Reader.ReadEncodedValue();
238 AsnReader Inner =
new(Section, Reader.RuleSet,
239 new AsnReaderOptions()
241 SkipSetSortOrderVerification =
true
244 if (Tag.TagValue == (
int)UniversalTagNumber.Sequence)
245 Inner = Inner.ReadSequence();
247 Inner = Inner.ReadSetOf(Tag);
251 Value = Array.Empty<
object?>();
257 if (Tag.TagValue == (
int)UniversalTagNumber.Sequence)
258 Value =
new Sequence(
new object?[] { FirstElement }, Section.ToArray());
260 Value =
new Set(
new object?[] { FirstElement }, Section.ToArray());
268 Elements.
Add(Element);
270 object?[] Elements2 = [.. Elements];
271 byte[] SubSection = Section.ToArray();
276 if (SecurityObject2.Configure(
new Vector(Elements2, SubSection)))
278 Value = SecurityObject2;
285 if (Tag.TagValue == (
int)UniversalTagNumber.Sequence)
286 Value =
new Sequence(Elements2, SubSection);
288 Value =
new Set(Elements2, SubSection);
292 case (
int)UniversalTagNumber.UtcTime:
293 Value = Reader.ReadUtcTime();
296 case (
int)UniversalTagNumber.GeneralizedTime:
297 Value = Reader.ReadGeneralizedTime();
305 else if (Tag.TagClass == TagClass.ContextSpecific)
307 ReadOnlyMemory<byte> Section = Reader.ReadEncodedValue();
309 if (Tag.IsConstructed)
311 AsnReader Inner =
new(Section, Reader.RuleSet);
315 Inner = Inner.ReadSequence(Tag);
319 Value = Array.Empty<
object?>();
325 Value =
new ContextSpecific(Tag.TagValue,
new object?[] { FirstElement }, Section.ToArray());
332 Elements.
Add(Element);
334 object?[] Elements2 = [.. Elements];
335 byte[] SubSection = Section.ToArray();
340 if (SecurityObject2.Configure(
new Vector(Elements2, SubSection)))
343 new object[] { SecurityObject2 }, SubSection);
356 Value = Section.ToArray();
362 Value = Section.ToArray();
380 return Inc(Oid, oidsNotRecognized);
391 return GetCounts(oidsNotRecognized, Clear);
401 return Inc(Oid, oidsNotConfigured);
412 return GetCounts(oidsNotConfigured, Clear);
422 return Inc(Name, algorithmsUsed);
435 if (Name ==
"Custom")
437 StringBuilder sb =
new();
439 sb.Append(
"Order: ");
440 sb.AppendLine(Curve.
Order.ToString(CultureInfo.InvariantCulture));
441 sb.Append(
"Cofactor: ");
442 sb.AppendLine(Curve.
Cofactor.ToString(CultureInfo.InvariantCulture));
443 sb.Append(
"BasePoint.X: ");
444 sb.AppendLine(Curve.
BasePoint.
X.ToString(CultureInfo.InvariantCulture));
445 sb.Append(
"BasePoint.Y: ");
446 sb.AppendLine(Curve.
BasePoint.
Y.ToString(CultureInfo.InvariantCulture));
450 sb.Append(
"Prime: ");
469 sb.AppendLine(
EdwardsCurve.
D.ToString(CultureInfo.InvariantCulture));
479 sb.AppendLine(Curve.GetType().FullName);
483 Inc(sb.ToString(), unrecognizedCurves);
506 return GetCounts(unrecognizedCurves, Clear);
515 public static int Inc(
string Key, SortedDictionary<string, int> Counts)
519 if (!Counts.TryGetValue(Key, out
int i))
526 if (i <
int.MaxValue)
540 public static KeyValuePair<string, int>[]
GetCounts(SortedDictionary<string, int> Counts,
bool Clear)
544 KeyValuePair<string, int>[] Result =
new KeyValuePair<string, int>[Counts.Count];
545 Counts.CopyTo(Result, 0);
562 if (objectConstructors is
null)
564 Dictionary<string, ConstructorInfo> Constructors = [];
576 Constructors[Obj.
Oid] = CI;
584 objectConstructors = Constructors;
587 if (objectConstructors.TryGetValue(Oid, out ConstructorInfo? CI2))
Static class for parsing and decoding security objects encoded using Abstract Syntax Notation 1 (ASN....
static bool TryDecodeDer(ICommunicationLayer? Client, byte[] Data, out object? Value)
Decodes a DER-encoded object.
static KeyValuePair< string, int >[] GetOidsNotConfigured(bool Clear)
Gets an array of OIDs that has not been configured properly.
static bool TryDecodeAsn1(AsnReader Reader, out object? Value)
Decodes the next ASN.1-encoded object.
static bool TryInstantiate(string Oid, [NotNullWhen(true)] out ISecurityObject? Object)
Tries to instantiate a new object of a given OID.
static bool TryDecodeAsn1(ICommunicationLayer? Client, AsnReader Reader, out object? Value)
Decodes the next ASN.1-encoded object.
static KeyValuePair< string, int >[] GetUnrecognizedEllipticCurvesUsed(bool Clear)
Gets an array of unrecognized Elliptic Curves that has been used.
static int Inc(string Key, SortedDictionary< string, int > Counts)
Increments a named counter
static int ReportOidNotRecognized(string Oid)
Records an OID as not recognized.
static bool TryDecodeDerAs(UniversalTagNumber TagNumber, byte[] Data, out object? Value)
Decodes a DER-encoded object.
static bool TryDecodeDerAs(ICommunicationLayer? Client, UniversalTagNumber TagNumber, byte[] Data, out object? Value)
Decodes a DER-encoded object.
static int ReportAlgorithmUse(EllipticCurve Curve)
Records an Elliptic Curve has been used.
static KeyValuePair< string, int >[] GetCounts(SortedDictionary< string, int > Counts, bool Clear)
Gets an array of counts
static KeyValuePair< string, int >[] GetOidsNotRecognized(bool Clear)
Gets an array of OIDs that has not been recognized.
static int ReportOidNotConfigured(string Oid)
Records an OID as not configured properly.
static bool TryDecodeDer(byte[] Data, out object? Value)
Decodes a DER-encoded object.
static KeyValuePair< string, int >[] GetAlgorithmsUsed(bool Clear)
Gets an array of algorithms that has been used.
static int ReportAlgorithmUse(string Name)
Records an Elliptic Curve has been used.
Abstract base class for security objects.
Static class managing the application event log. Applications and services log events on this static ...
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
A chunked list is a linked list of chunks of objects of type T .
void Add(T Item)
Adds an item to the collection.
Static class that dynamically manages types and interfaces available in the runtime environment.
static object[] NoParameters
Contains an empty array of parameter values.
static Type[] GetTypesImplementingInterface(string InterfaceFullName)
Gets all types implementing a given interface.
static ConstructorInfo GetDefaultConstructor(Type Type)
Gets the default constructor of a type, if one exists.
BigInteger D
d coefficient of Edwards curve.
Base class of Edwards curves (x²+y²=1+dx²y²) over a prime field.
Base class of Twisted Edwards curves (-x²+y²=1+dx²y²) over a prime field.
Abstract base class for elliptic curves.
abstract string CurveName
Name of curve.
BigInteger Order
Order of curve.
int Cofactor
Cofactor of curve.
PointOnCurve BasePoint
Base-point of curve.
Base class of Montgomery curves (y²=x³+Ax²+x), with birational Edwards equivalent over a prime field.
BigInteger A
Coefficient a.
Base class of Elliptic curves over a prime field.
BigInteger Prime
Prime of curve.
Base class of Weierstrass curves (y²=x³+ax+b) over a prime field.
BigInteger A
Coefficient a.
BigInteger B
Coefficient b.
Interface for security objects.
bool IsConfigured
If the object has been configured.
string Oid
OID identifying the object.
void Warning(string Warning)
Called to inform the viewer of a warning state.
Interface for observable classes implementing communication protocols.
class ContextSpecific(int Tag, Array Elements, byte[] SubSection)
A context-specific object (or set of objects).
class Sequence(Array Elements, byte[] SubSection)
A generic sequence class used if dedicated security objects cannot be found.
class Set(Array Elements, byte[] SubSection)
A generic set class used if dedicated security objects cannot be found.