Skip to content

Commit f0e143e

Browse files
committed
massive cleanup of Asn1Utils class
1 parent da6fabb commit f0e143e

File tree

7 files changed

+163
-587
lines changed

7 files changed

+163
-587
lines changed

Asn1Parser/Asn1Class.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,6 @@ public enum Asn1Class : System.Byte {
2323
/// <summary>
2424
/// Represents Private tag class.
2525
/// </summary>
26-
PRIVATE = 192, // 0xc0
27-
/// <summary>
28-
/// Represents universal tag mask that allows to extract universal type from non-universal class.
29-
/// </summary>
30-
UNIVERSAL_MASK = 31
26+
PRIVATE = 192 // 0xc0
3127
}
3228
}

Asn1Parser/Asn1Parser.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<PropertyGroup>
33
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
44
<Title>High-performance and robust .NET ASN.1 DER parser</Title>
5-
<Version>1.2.7.62</Version>
5+
<Version>1.2.8.62</Version>
66
<Authors>Vadims Podans, PKI Solutions Inc.</Authors>
77
<Company>PKI Solutions LLC</Company>
88
<Description>ASN.1 binary parser and utility set for binary data encoded with Distinguished Encoding Rules (DER).</Description>

Asn1Parser/Asn1Reader.cs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -527,12 +527,42 @@ public void Reset() {
527527
/// <returns>ASN.1 object that represents current tag.</returns>
528528
public UniversalTagBase GetTagObject() {
529529
switch (Tag) {
530-
case (Byte)Asn1Type.OBJECT_IDENTIFIER:
531-
return new Asn1ObjectIdentifier(this);
530+
case (Byte)Asn1Type.BOOLEAN:
531+
return new Asn1Boolean(this);
532+
case (Byte)Asn1Type.INTEGER:
533+
return new Asn1Integer(this);
532534
case (Byte)Asn1Type.BIT_STRING:
533535
return new Asn1BitString(this);
536+
case (Byte)Asn1Type.OCTET_STRING:
537+
return new Asn1OctetString(this);
538+
case (Byte)Asn1Type.NULL:
539+
return new Asn1Null(this);
540+
case (Byte)Asn1Type.OBJECT_IDENTIFIER:
541+
return new Asn1ObjectIdentifier(this);
542+
case (Byte)Asn1Type.ENUMERATED:
543+
return new Asn1Enumerated(this);
544+
case (Byte)Asn1Type.UTF8String:
545+
return new Asn1UTF8String(this);
546+
case (Byte)Asn1Type.NumericString:
547+
return new Asn1NumericString(this);
548+
case (Byte)Asn1Type.PrintableString:
549+
return new Asn1PrintableString(this);
550+
case (Byte)Asn1Type.TeletexString:
551+
return new Asn1TeletexString(this);
552+
case (Byte)Asn1Type.IA5String:
553+
return new Asn1IA5String(this);
554+
case (Byte)Asn1Type.UTCTime:
555+
return new Asn1UtcTime(this);
556+
case (Byte)Asn1Type.GeneralizedTime:
557+
return new Asn1GeneralizedTime(this);
558+
case (Byte)Asn1Type.VisibleString:
559+
return new Asn1VisibleString(this);
560+
case (Byte)Asn1Type.UniversalString:
561+
return new Asn1UniversalString(this);
562+
case (Byte)Asn1Type.BMPString:
563+
return new Asn1BMPString(this);
534564
default:
535-
return new UniversalTagBase(this);
565+
return new Asn1AnyType(this);
536566
}
537567
}
538568
/// <summary>

Asn1Parser/Asn1Utils.cs

Lines changed: 25 additions & 577 deletions
Large diffs are not rendered by default.

Asn1Parser/Universal/Asn1DateTime.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,37 @@ protected Asn1DateTime(Asn1Reader asn, Asn1Type? type) : base(asn, type) { }
2626
/// </summary>
2727
public DateTime Value { get; protected set; }
2828

29+
/// <summary>
30+
/// Encodes a .NET DateTime object to a ASN.1-encoded byte array. This method is designed to conform
31+
/// <see href="http://tools.ietf.org/html/rfc5280">RFC 5280</see> requirement, so dates before 1950 and
32+
/// after 2050 year are required to be encoded by using Generalized Time encoding. UTC Time encoding is not allowed
33+
/// for periods beyond 1950 - 2049 years.
34+
/// </summary>
35+
/// <param name="time">
36+
/// An instance of <see cref="DateTime"/> object.</param> Value in this parameter is treated as local time.
37+
/// <param name="zone">
38+
/// Specifies the time zone for the value in <strong>time</strong> parameter.
39+
/// </param>
40+
/// <returns>ASN.1 type object.</returns>
41+
/// <remarks>
42+
/// If the <strong>Year</strong> value of the <strong>time</strong> object is less or equals to 2049
43+
/// and greater or equals to 1950, an <see cref="Asn1UtcTime"/> object is returned.
44+
/// If year value is outside of 1950-2049 range, an <see cref="Asn1GeneralizedTime"/> object is returned.
45+
/// <para>
46+
/// If <strong>zone</strong> parameter is set to <strong>NULL</strong>, date and time in <strong>time</strong>
47+
/// parameter will be converted to a Zulu time (Universal time). If zone information is not <strong>NULL</strong>,
48+
/// date and time in <strong>time</strong> parameter will be converted to a GMT time and time zone will be added
49+
/// to encoded value.
50+
/// </para>
51+
/// </remarks>
52+
/// <seealso cref="Asn1UtcTime"/>
53+
/// <seealso cref="Asn1GeneralizedTime"/>
54+
public static Asn1DateTime CreateRfcDateTime(DateTime time, TimeZoneInfo zone = null) {
55+
if (time.Year < 2050 && time.Year >= 1950) {
56+
return new Asn1UtcTime(time, zone);
57+
}
58+
59+
return new Asn1GeneralizedTime(time, zone);
60+
}
2961
}
3062
}

Asn1Parser/Universal/Asn1ObjectIdentifier.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ static Boolean validateOidString(String oid, out List<BigInteger> tokens) {
158158
public override String GetDisplayValue() {
159159
return String.IsNullOrEmpty(Value.FriendlyName)
160160
? Value.Value
161-
: Value.FriendlyName + " (" + Value.Value + ")";
161+
: $"{Value.FriendlyName} ({Value.Value})";
162162
}
163163
}
164164
}

Asn1Parser/Universal/Asn1String.cs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,33 @@
11
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
24

35
namespace SysadminsLV.Asn1Parser.Universal {
46
/// <summary>
57
/// Represents base class for ASN.1 string types.
68
/// </summary>
79
public abstract class Asn1String : UniversalTagBase {
10+
#region allowedStringTypes:
11+
const Int32 CERT_RDN_ANY_TYPE = 0;
12+
const Int32 CERT_RDN_ENCODED_BLOB = 1;
13+
const Int32 CERT_RDN_OCTET_STRING = 2;
14+
const Int32 CERT_RDN_NUMERIC_STRING = 3;
15+
const Int32 CERT_RDN_PRINTABLE_STRING = 4;
16+
const Int32 CERT_RDN_TELETEX_STRING = 5;
17+
const Int32 CERT_RDN_T61_STRING = 5;
18+
const Int32 CERT_RDN_VIDEOTEX_STRING = 6;
19+
const Int32 CERT_RDN_IA5_STRING = 7;
20+
const Int32 CERT_RDN_GRAPHIC_STRING = 8; // not used
21+
const Int32 CERT_RDN_VISIBLE_STRING = 9;
22+
const Int32 CERT_RDN_ISO646_STRING = 9;
23+
const Int32 CERT_RDN_GENERAL_STRING = 10; // not used
24+
const Int32 CERT_RDN_UNIVERSAL_STRING = 11;
25+
const Int32 CERT_RDN_INT4_STRING = 11;
26+
const Int32 CERT_RDN_BMP_STRING = 12;
27+
const Int32 CERT_RDN_UNICODE_STRING = 12;
28+
const Int32 CERT_RDN_UTF8_STRING = 13;
29+
#endregion
30+
831
/// <summary>
932
/// Initializes a new instance of <strong>Asn1String</strong> class.
1033
/// </summary>
@@ -22,5 +45,52 @@ protected Asn1String(Asn1Reader asn, Asn1Type? type) : base(asn, type) { }
2245
/// </summary>
2346
public String Value { get; protected set; }
2447

48+
/// <summary>
49+
/// Decodes any ASN.1-encoded binary string into ASN.1 string type instance.
50+
/// </summary>
51+
/// <param name="rawData">Encoded ASN.1 string.</param>
52+
/// <param name="allowedStringTypes">An optional collection of allowed string allowedStringTypes.</param>
53+
/// <exception cref="ArgumentNullException">
54+
/// <strong>rawData</strong> parameter is null.
55+
/// </exception>
56+
/// <exception cref="ArgumentException">
57+
/// <strong>rawData</strong> parameter is either too small or is not allowed by restriction.
58+
/// </exception>
59+
/// <returns>ASN.1 string type instance.</returns>
60+
/// <exception cref="Asn1InvalidTagException">
61+
/// Input data is not valid string type.
62+
/// </exception>
63+
public static Asn1String DecodeAnyString(Byte[] rawData, IEnumerable<Asn1Type> allowedStringTypes = null) {
64+
if (rawData == null) {
65+
throw new ArgumentNullException(nameof(rawData));
66+
}
67+
if (rawData.Length < 2) {
68+
throw new ArgumentException("Raw data must have at least tag (1 byte) and length components (1 byte) in TLV structure.");
69+
}
70+
71+
IEnumerable<Asn1Type> asn1Types = allowedStringTypes?.ToList();
72+
if (asn1Types != null && !asn1Types.Contains((Asn1Type)rawData[0])) {
73+
throw new ArgumentException("Input string is not permitted by restriction.");
74+
}
75+
var tag = (Asn1Type)(rawData[0] & (Int32)Asn1Type.TAG_MASK);
76+
switch (tag) {
77+
case Asn1Type.IA5String:
78+
return new Asn1IA5String(rawData);
79+
case Asn1Type.PrintableString:
80+
return new Asn1PrintableString(rawData);
81+
case Asn1Type.VisibleString:
82+
return new Asn1VisibleString(rawData);
83+
case Asn1Type.UTF8String:
84+
return new Asn1UTF8String(rawData);
85+
case Asn1Type.UniversalString:
86+
return new Asn1UniversalString(rawData);
87+
case Asn1Type.BMPString:
88+
return new Asn1BMPString(rawData);
89+
case Asn1Type.TeletexString:
90+
return new Asn1TeletexString(rawData);
91+
default:
92+
throw new Asn1InvalidTagException("Input data is not valid string.");
93+
}
94+
}
2595
}
2696
}

0 commit comments

Comments
 (0)