Skip to content

Commit 2e4b7ab

Browse files
committed
fixed OID decoder #6 and updated related unit tests
1 parent a8e713c commit 2e4b7ab

2 files changed

Lines changed: 47 additions & 51 deletions

File tree

Asn1Parser/Universal/Asn1ObjectIdentifier.cs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ public sealed class Asn1ObjectIdentifier : Asn1Universal {
2323
/// <exception cref="Asn1InvalidTagException">
2424
/// The current state of <strong>ASN1</strong> object is not object identifier.
2525
/// </exception>
26-
///
2726
public Asn1ObjectIdentifier(Asn1Reader asn) : base(asn, TYPE) {
2827
Value = new Oid(decode(asn));
2928
}
@@ -63,7 +62,7 @@ public Asn1ObjectIdentifier(Oid oid) : base(TYPE) {
6362

6463
void m_encode(Oid oid) {
6564
if (String.IsNullOrWhiteSpace(oid.Value)) {
66-
Initialize(new Asn1Reader(new Byte[] { Tag, 0 }));
65+
Initialize(new Asn1Reader([Tag, 0]));
6766
Value = new Oid();
6867
return;
6968
}
@@ -121,29 +120,35 @@ static Byte[] encode(IList<BigInteger> tokens) {
121120
}
122121
static String decode(Asn1Reader asn) {
123122
var SB = new StringBuilder();
124-
Int32 token = 0;
123+
Boolean topArcsProcessed = false;
125124
for (Int32 i = 0; i < asn.PayloadLength; i++) {
126125
Int32 pi = asn.PayloadStartOffset + i;
127-
if (token == 0) {
128-
SB.Append(asn[pi] / 40);
129-
SB.Append("." + asn[pi] % 40);
130-
token++;
131-
continue;
132-
}
126+
133127
BigInteger value = 0;
134128
Boolean proceed;
135129
do {
136130
value <<= 7;
137131
value += asn[pi] & 0x7f;
138132
proceed = (asn[pi] & 0x80) > 0;
139133
if (proceed) {
140-
token++;
141134
i++;
142135
pi++;
143136
}
144137
} while (proceed);
138+
if (!topArcsProcessed) {
139+
topArcsProcessed = true;
140+
// max value for first two arcs in ITU-T and ISO is 79 (OID=1.39). If this value is larger, then
141+
// it belongs to 'joint-iso-itu-t' (OID=2.x)
142+
if (value >= 80) {
143+
SB.Append("2.").Append(value - 80);
144+
} else {
145+
SB.Append(value / 40);
146+
SB.Append("." + value % 40);
147+
}
148+
continue;
149+
}
150+
145151
SB.Append("." + value);
146-
token++;
147152
}
148153
return SB.ToString();
149154
}

tests/Asn1Parser.Tests/Asn1OidTests.cs

Lines changed: 31 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,10 @@ namespace Asn1Parser.Tests;
77

88
[TestClass]
99
public class Asn1OidTests {
10-
[TestMethod, Description("Test if at least two arcs are encoded.")]
11-
public void TestMinStringLengthEncode() {
12-
var oid = new Asn1ObjectIdentifier("0.0");
13-
Assert.AreEqual("0.0", oid.Value.Value);
14-
String encodedB64 = Convert.ToBase64String(oid.GetRawData());
15-
// must be 06 01 00
16-
Assert.AreEqual("BgEA", encodedB64);
17-
}
1810
[TestMethod, Description("Test if at least two arcs are required.")]
19-
public void TestMinStringLengthDecode() {
20-
Byte[] rawData = Convert.FromBase64String("BgEA");
21-
var oid = new Asn1ObjectIdentifier(rawData);
22-
Assert.AreEqual("0.0", oid.Value.Value);
23-
String encodedB64 = Convert.ToBase64String(oid.GetRawData());
11+
public void TestMinStringLength() {
2412
// must be 06 01 00
25-
Assert.AreEqual("BgEA", encodedB64);
13+
testOidBiDirectional("0.0", "BgEA");
2614
}
2715
[TestMethod, Description("Test if single arc encoding fails.")]
2816
[ExpectedException(typeof(InvalidDataException))]
@@ -31,7 +19,8 @@ public void TestSingleArcEncodeFail() {
3119
}
3220
[TestMethod, Description("Test if 2nd arc under 'itu-t' root node encoded up to 39.")]
3321
public void TestItuRootArcConstraintsPass() {
34-
new Asn1ObjectIdentifier("0.39");
22+
// must be 06 01 27
23+
testOidBiDirectional("0.39", "BgEn");
3524
}
3625
[TestMethod, Description("Test if 2nd arc under 'itu-t' root node >39 fails.")]
3726
[ExpectedException(typeof(InvalidDataException))]
@@ -40,7 +29,8 @@ public void TestItuRootArcConstraintsFail() {
4029
}
4130
[TestMethod, Description("Test if 2nd arc under 'iso' root node encoded up to 39.")]
4231
public void TestIsoRootArcConstraintsPass() {
43-
new Asn1ObjectIdentifier("1.39");
32+
// must be 06 01 4f
33+
testOidBiDirectional("1.39", "BgFP");
4434
}
4535
[TestMethod, Description("Test if 2nd arc under 'iso' root node >39 fails.")]
4636
[ExpectedException(typeof(InvalidDataException))]
@@ -49,38 +39,39 @@ public void TestIsoRootArcConstraintsFail() {
4939
}
5040
[TestMethod, Description("Test if 2nd arc under 'joint-iso-itu-t' root do not impose 2nd arc limits.")]
5141
public void TestJointIsoItuRootArcPass() {
52-
new Asn1ObjectIdentifier("2.40");
42+
// must be 06 01 78
43+
testOidBiDirectional("2.40", "BgF4");
44+
}
45+
[TestMethod, Description("Test random cert template OID, which includes short and long arcs")]
46+
public void TestCertTemplateOid() {
47+
testOidBiDirectional("1.3.6.1.4.1.311.21.8.149510.7314491.15746959.9320746.3700693.37.1.25", "Bh8rBgEEAYI3FQiJkAaDvrg7h8GPD4S48iqB4e9VJQEZ");
5348
}
5449
[TestMethod, Description("Test if first first two arcs can span multiple bytes if first byte >= 128")]
5550
public void TestLargeTopArcs() {
56-
var oid = new Asn1ObjectIdentifier("2.999");
57-
String encodedB64 = Convert.ToBase64String(oid.GetRawData());
51+
// must be 06 01 50
52+
// OID 2.0 is identical to invalid 1.40, which is prohibited
53+
testOidBiDirectional("2.0", "BgFQ");
5854
// must be 06 02 88 37
59-
Assert.AreEqual("BgKINw==", encodedB64);
60-
61-
oid = new Asn1ObjectIdentifier("2.999.3");
62-
encodedB64 = Convert.ToBase64String(oid.GetRawData());
55+
testOidBiDirectional("2.999", "BgKINw==");
6356
// must be 06 03 88 37 03
64-
Assert.AreEqual("BgOINwM=", encodedB64);
65-
66-
oid = new Asn1ObjectIdentifier("2.251.9.121");
67-
encodedB64 = Convert.ToBase64String(oid.GetRawData());
57+
testOidBiDirectional("2.999.3", "BgOINwM=");
6858
// must be 06 04 82 4B 09 79
69-
Assert.AreEqual("BgSCSwl5", encodedB64);
70-
71-
oid = new Asn1ObjectIdentifier("2.999.1234");
72-
encodedB64 = Convert.ToBase64String(oid.GetRawData());
59+
testOidBiDirectional("2.251.9.121", "BgSCSwl5");
7360
// must be 06 04 88 37 89 52
74-
Assert.AreEqual("BgSIN4lS", encodedB64);
75-
76-
oid = new Asn1ObjectIdentifier("2.176.9.121");
77-
encodedB64 = Convert.ToBase64String(oid.GetRawData());
61+
testOidBiDirectional("2.999.1234", "BgSIN4lS");
7862
// must be 06 04 82 00 09 79
79-
Assert.AreEqual("BgSCAAl5", encodedB64);
80-
81-
oid = new Asn1ObjectIdentifier("2.81.0.9.121");
82-
encodedB64 = Convert.ToBase64String(oid.GetRawData());
63+
testOidBiDirectional("2.176.9.121", "BgSCAAl5");
8364
// must be 06 04 79 00 09 79
84-
Assert.AreEqual("BgWBIQAJeQ==", encodedB64);
65+
testOidBiDirectional("2.81.0.9.121", "BgWBIQAJeQ==");
66+
}
67+
68+
static void testOidBiDirectional(String oidString, String expectedB64) {
69+
// test OID string -> binary encoding process
70+
var oid = new Asn1ObjectIdentifier(oidString);
71+
String encodedB64 = Convert.ToBase64String(oid.GetRawData());
72+
Assert.AreEqual(expectedB64, encodedB64);
73+
// test binary -> OID string decoding process
74+
oid = new Asn1ObjectIdentifier(Convert.FromBase64String(expectedB64));
75+
Assert.AreEqual(oidString, oid.Value.Value);
8576
}
8677
}

0 commit comments

Comments
 (0)