Skip to content

Commit a8e713c

Browse files
committed
Addressed OID encoding part of bug #6. Decoder fix is pending.
1 parent edf01cb commit a8e713c

2 files changed

Lines changed: 82 additions & 13 deletions

File tree

Asn1Parser/Universal/Asn1ObjectIdentifier.cs

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ namespace SysadminsLV.Asn1Parser.Universal;
1212
/// </summary>
1313
public sealed class Asn1ObjectIdentifier : Asn1Universal {
1414
const Asn1Type TYPE = Asn1Type.OBJECT_IDENTIFIER;
15+
const Byte ITU_T_ROOT = 0;
16+
const Byte ISO_ROOT = 1;
1517

1618
/// <summary>
1719
/// Initializes a new instance of the <strong>Asn1ObjectIdentifier</strong> class from an existing
@@ -77,17 +79,29 @@ void m_encode(Oid oid) {
7779

7880
static Byte[] encode(IList<BigInteger> tokens) {
7981
var rawOid = new List<Byte>();
80-
for (Int32 token = 0; token < tokens.Count; token++) {
81-
// first two arcs are encoded in a single byte
82-
switch (token) {
82+
for (Int32 tokenIndex = 0; tokenIndex < tokens.Count; tokenIndex++) {
83+
BigInteger token = tokens[tokenIndex];
84+
BigInteger temp = token;
85+
// first two arcs are encoded as a single arc
86+
switch (tokenIndex) {
8387
case 0:
84-
rawOid.Add((Byte)(40 * tokens[token] + tokens[token + 1]));
85-
continue;
88+
//
89+
token = 40 * token + tokens[tokenIndex + 1];
90+
// if first two arcs can be encoded using 7 bits (single byte where most significant bit is 0),
91+
// then nothing fancy, simply add it as single byte.
92+
if (token < 0x80) {
93+
rawOid.Add((Byte)token);
94+
continue;
95+
}
96+
// otherwise first two arcs are encoded using multiple bytes, and we have to go through
97+
// standard OID arc encoding routine.
98+
temp = token;
99+
break;
100+
// we already handled 2nd arc, so skip its processing.
86101
case 1:
87102
continue;
88103
}
89104
Int16 bitLength = 0;
90-
BigInteger temp = tokens[token];
91105
// calculate how many bits are occupied by the current integer value
92106
do {
93107
temp = (BigInteger)Math.Floor((Double)temp / 2);
@@ -99,9 +113,9 @@ static Byte[] encode(IList<BigInteger> tokens) {
99113
// http://msdn.microsoft.com/en-us/library/bb540809(v=vs.85).aspx
100114
// loop may not execute if arc value is less than 128.
101115
for (Int32 index = (bitLength - 1) / 7; index > 0; index--) {
102-
rawOid.Add((Byte)(0x80 | ((tokens[token] >> (index * 7)) & 0x7f)));
116+
rawOid.Add((Byte)(0x80 | ((token >> (index * 7)) & 0x7f)));
103117
}
104-
rawOid.Add((Byte)(tokens[token] & 0x7f));
118+
rawOid.Add((Byte)(token & 0x7f));
105119
}
106120
return rawOid.ToArray();
107121
}
@@ -143,8 +157,16 @@ static Boolean validateOidString(String oid, out List<BigInteger> tokens) {
143157
for (Int32 index = 0; index < strTokens.Length; index++) {
144158
try {
145159
var value = BigInteger.Parse(strTokens[index]);
146-
if (index == 0 && value > 2 || index == 1 && value > 39) {
147-
return false;
160+
if (index == 0) {
161+
// check if root arc is 0, 1, or 2
162+
if (value > 2) {
163+
return false;
164+
}
165+
var secondArc = BigInteger.Parse(strTokens[1]);
166+
// check if 2nd arc under ITU-T and ISO is <=39
167+
if ((Byte)value is ITU_T_ROOT or ISO_ROOT && secondArc > 39) {
168+
return false;
169+
}
148170
}
149171
tokens.Add(value);
150172
} catch {

tests/Asn1Parser.Tests/Asn1OidTests.cs

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public void TestMinStringLengthEncode() {
1212
var oid = new Asn1ObjectIdentifier("0.0");
1313
Assert.AreEqual("0.0", oid.Value.Value);
1414
String encodedB64 = Convert.ToBase64String(oid.GetRawData());
15+
// must be 06 01 00
1516
Assert.AreEqual("BgEA", encodedB64);
1617
}
1718
[TestMethod, Description("Test if at least two arcs are required.")]
@@ -20,20 +21,66 @@ public void TestMinStringLengthDecode() {
2021
var oid = new Asn1ObjectIdentifier(rawData);
2122
Assert.AreEqual("0.0", oid.Value.Value);
2223
String encodedB64 = Convert.ToBase64String(oid.GetRawData());
24+
// must be 06 01 00
2325
Assert.AreEqual("BgEA", encodedB64);
2426
}
2527
[TestMethod, Description("Test if single arc encoding fails.")]
2628
[ExpectedException(typeof(InvalidDataException))]
2729
public void TestSingleArcEncodeFail() {
2830
new Asn1ObjectIdentifier("0");
2931
}
30-
[TestMethod, Description("Test if 2nd arc under 'ITU' root node encoded up to 39.")]
32+
[TestMethod, Description("Test if 2nd arc under 'itu-t' root node encoded up to 39.")]
3133
public void TestItuRootArcConstraintsPass() {
32-
new Asn1ObjectIdentifier("1.39");
34+
new Asn1ObjectIdentifier("0.39");
3335
}
34-
[TestMethod, Description("Test if 2nd arc under 'ITU' root node >39 fails.")]
36+
[TestMethod, Description("Test if 2nd arc under 'itu-t' root node >39 fails.")]
3537
[ExpectedException(typeof(InvalidDataException))]
3638
public void TestItuRootArcConstraintsFail() {
39+
new Asn1ObjectIdentifier("0.40");
40+
}
41+
[TestMethod, Description("Test if 2nd arc under 'iso' root node encoded up to 39.")]
42+
public void TestIsoRootArcConstraintsPass() {
43+
new Asn1ObjectIdentifier("1.39");
44+
}
45+
[TestMethod, Description("Test if 2nd arc under 'iso' root node >39 fails.")]
46+
[ExpectedException(typeof(InvalidDataException))]
47+
public void TestIsoRootArcConstraintsFail() {
3748
new Asn1ObjectIdentifier("1.40");
3849
}
50+
[TestMethod, Description("Test if 2nd arc under 'joint-iso-itu-t' root do not impose 2nd arc limits.")]
51+
public void TestJointIsoItuRootArcPass() {
52+
new Asn1ObjectIdentifier("2.40");
53+
}
54+
[TestMethod, Description("Test if first first two arcs can span multiple bytes if first byte >= 128")]
55+
public void TestLargeTopArcs() {
56+
var oid = new Asn1ObjectIdentifier("2.999");
57+
String encodedB64 = Convert.ToBase64String(oid.GetRawData());
58+
// 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());
63+
// 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());
68+
// 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());
73+
// 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());
78+
// 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());
83+
// must be 06 04 79 00 09 79
84+
Assert.AreEqual("BgWBIQAJeQ==", encodedB64);
85+
}
3986
}

0 commit comments

Comments
 (0)