From 8bef2160dc81d3c29d5bf18950f4fdeaa4da06d0 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 8 Nov 2021 22:57:03 +0700 Subject: ASN.1: Add support for relative OIDs --- crypto/BouncyCastle.Android.csproj | 1 + crypto/BouncyCastle.csproj | 1 + crypto/BouncyCastle.iOS.csproj | 1 + crypto/crypto.csproj | 10 + crypto/src/asn1/Asn1InputStream.cs | 2 + crypto/src/asn1/Asn1RelativeOid.cs | 296 +++++++++++++++++++++ crypto/src/asn1/DerObjectIdentifier.cs | 231 +++++----------- crypto/src/asn1/util/Asn1Dump.cs | 4 + crypto/test/UnitTests.csproj | 1 + crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs | 1 + crypto/test/src/asn1/test/OIDTest.cs | 98 +++---- crypto/test/src/asn1/test/RegressionTest.cs | 3 +- crypto/test/src/asn1/test/RelativeOidTest.cs | 129 +++++++++ 13 files changed, 563 insertions(+), 215 deletions(-) create mode 100644 crypto/src/asn1/Asn1RelativeOid.cs create mode 100644 crypto/test/src/asn1/test/RelativeOidTest.cs diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj index 3e75ff3a4..567351082 100644 --- a/crypto/BouncyCastle.Android.csproj +++ b/crypto/BouncyCastle.Android.csproj @@ -73,6 +73,7 @@ + diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj index 183e4b3d8..aec91b946 100644 --- a/crypto/BouncyCastle.csproj +++ b/crypto/BouncyCastle.csproj @@ -67,6 +67,7 @@ + diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj index 99bd91fbd..83d8c66a2 100644 --- a/crypto/BouncyCastle.iOS.csproj +++ b/crypto/BouncyCastle.iOS.csproj @@ -68,6 +68,7 @@ + diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index bb35c6f99..0f90a842d 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -203,6 +203,11 @@ SubType = "Code" BuildAction = "Compile" /> + + > 7) - 0x7F; + + private readonly string identifier; + private byte[] contents; + + public Asn1RelativeOid(string identifier) + { + if (identifier == null) + throw new ArgumentNullException("identifier"); + if (!IsValidIdentifier(identifier, 0)) + throw new FormatException("string " + identifier + " not a relative OID"); + + this.identifier = identifier; + } + + private Asn1RelativeOid(Asn1RelativeOid oid, string branchID) + { + if (!IsValidIdentifier(branchID, 0)) + throw new FormatException("string " + branchID + " not a valid relative OID branch"); + + this.identifier = oid.Id + "." + branchID; + } + + private Asn1RelativeOid(byte[] contents, bool clone) + { + this.identifier = ParseContents(contents); + this.contents = clone ? Arrays.Clone(contents) : contents; + } + + public virtual Asn1RelativeOid Branch(string branchID) + { + return new Asn1RelativeOid(this, branchID); + } + + public string Id + { + get { return identifier; } + } + + public override string ToString() + { + return identifier; + } + + protected override bool Asn1Equals(Asn1Object asn1Object) + { + Asn1RelativeOid that = asn1Object as Asn1RelativeOid; + return null != that + && this.identifier == that.identifier; + } + + protected override int Asn1GetHashCode() + { + return identifier.GetHashCode(); + } + + internal override bool EncodeConstructed() + { + return false; + } + + internal override int EncodedLength(bool withID) + { + return Asn1OutputStream.GetLengthOfEncodingDL(withID, GetContents().Length); + } + + internal override void Encode(Asn1OutputStream asn1Out, bool withID) + { + asn1Out.WriteEncodingDL(withID, Asn1Tags.RelativeOid, GetContents()); + } + + private void DoOutput(MemoryStream bOut) + { + OidTokenizer tok = new OidTokenizer(identifier); + while (tok.HasMoreTokens) + { + string token = tok.NextToken(); + if (token.Length <= 18) + { + WriteField(bOut, Int64.Parse(token)); + } + else + { + WriteField(bOut, new BigInteger(token)); + } + } + } + + private byte[] GetContents() + { + lock (this) + { + if (contents == null) + { + MemoryStream bOut = new MemoryStream(); + DoOutput(bOut); + contents = bOut.ToArray(); + } + + return contents; + } + } + + internal static Asn1RelativeOid CreatePrimitive(byte[] contents, bool clone) + { + return new Asn1RelativeOid(contents, clone); + } + + internal static bool IsValidIdentifier(string identifier, int from) + { + int digitCount = 0; + + int pos = identifier.Length; + while (--pos >= from) + { + char ch = identifier[pos]; + + if (ch == '.') + { + if (0 == digitCount || (digitCount > 1 && identifier[pos + 1] == '0')) + return false; + + digitCount = 0; + } + else if ('0' <= ch && ch <= '9') + { + ++digitCount; + } + else + { + return false; + } + } + + if (0 == digitCount || (digitCount > 1 && identifier[pos + 1] == '0')) + return false; + + return true; + } + + internal static void WriteField(Stream outputStream, long fieldValue) + { + byte[] result = new byte[9]; + int pos = 8; + result[pos] = (byte)((int)fieldValue & 0x7F); + while (fieldValue >= (1L << 7)) + { + fieldValue >>= 7; + result[--pos] = (byte)((int)fieldValue | 0x80); + } + outputStream.Write(result, pos, 9 - pos); + } + + internal static void WriteField(Stream outputStream, BigInteger fieldValue) + { + int byteCount = (fieldValue.BitLength + 6) / 7; + if (byteCount == 0) + { + outputStream.WriteByte(0); + } + else + { + BigInteger tmpValue = fieldValue; + byte[] tmp = new byte[byteCount]; + for (int i = byteCount - 1; i >= 0; i--) + { + tmp[i] = (byte)(tmpValue.IntValue | 0x80); + tmpValue = tmpValue.ShiftRight(7); + } + tmp[byteCount - 1] &= 0x7F; + outputStream.Write(tmp, 0, tmp.Length); + } + } + + private static string ParseContents(byte[] contents) + { + StringBuilder objId = new StringBuilder(); + long value = 0; + BigInteger bigValue = null; + bool first = true; + + for (int i = 0; i != contents.Length; i++) + { + int b = contents[i]; + + if (value <= LongLimit) + { + value += b & 0x7F; + if ((b & 0x80) == 0) + { + if (first) + { + first = false; + } + else + { + objId.Append('.'); + } + + objId.Append(value); + value = 0; + } + else + { + value <<= 7; + } + } + else + { + if (bigValue == null) + { + bigValue = BigInteger.ValueOf(value); + } + bigValue = bigValue.Or(BigInteger.ValueOf(b & 0x7F)); + if ((b & 0x80) == 0) + { + if (first) + { + first = false; + } + else + { + objId.Append('.'); + } + + objId.Append(bigValue); + bigValue = null; + value = 0; + } + else + { + bigValue = bigValue.ShiftLeft(7); + } + } + } + + return objId.ToString(); + } + } +} diff --git a/crypto/src/asn1/DerObjectIdentifier.cs b/crypto/src/asn1/DerObjectIdentifier.cs index 4821d3b22..08451b82f 100644 --- a/crypto/src/asn1/DerObjectIdentifier.cs +++ b/crypto/src/asn1/DerObjectIdentifier.cs @@ -1,7 +1,6 @@ using System; using System.IO; using System.Text; -using System.Text.RegularExpressions; using Org.BouncyCastle.Math; using Org.BouncyCastle.Utilities; @@ -16,9 +15,6 @@ namespace Org.BouncyCastle.Asn1 return CreatePrimitive(contents, true); } - private readonly string identifier; - private byte[] contents; - /** * return an Oid from the passed in object * @@ -51,31 +47,26 @@ namespace Org.BouncyCastle.Asn1 throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj"); } - /** - * return an object Identifier from a tagged object. - * - * @param obj the tagged object holding the object we want - * @param explicitly true if the object is meant to be explicitly - * tagged false otherwise. - * @exception ArgumentException if the tagged object cannot - * be converted. - */ - public static DerObjectIdentifier GetInstance( - Asn1TaggedObject obj, - bool explicitly) + public static DerObjectIdentifier GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) { - Asn1Object o = obj.GetObject(); + Asn1Object baseObject = taggedObject.GetObject(); - if (explicitly || o is DerObjectIdentifier) + if (declaredExplicit || baseObject is DerObjectIdentifier) { - return GetInstance(o); + return GetInstance(baseObject); } - return FromContents(Asn1OctetString.GetInstance(o).GetOctets()); + return FromContents(Asn1OctetString.GetInstance(baseObject).GetOctets()); } - public DerObjectIdentifier( - string identifier) + private const long LongLimit = (Int64.MaxValue >> 7) - 0x7F; + + private static readonly DerObjectIdentifier[] cache = new DerObjectIdentifier[1024]; + + private readonly string identifier; + private byte[] contents; + + public DerObjectIdentifier(string identifier) { if (identifier == null) throw new ArgumentNullException("identifier"); @@ -85,18 +76,18 @@ namespace Org.BouncyCastle.Asn1 this.identifier = identifier; } - internal DerObjectIdentifier(DerObjectIdentifier oid, string branchID) + private DerObjectIdentifier(DerObjectIdentifier oid, string branchID) { - if (!IsValidBranchID(branchID, 0)) + if (!Asn1RelativeOid.IsValidIdentifier(branchID, 0)) throw new ArgumentException("string " + branchID + " not a valid OID branch", "branchID"); this.identifier = oid.Id + "." + branchID; } - // TODO Change to ID? - public string Id + private DerObjectIdentifier(byte[] contents, bool clone) { - get { return identifier; } + this.identifier = ParseContents(contents); + this.contents = clone ? Arrays.Clone(contents) : contents; } public virtual DerObjectIdentifier Branch(string branchID) @@ -104,6 +95,11 @@ namespace Org.BouncyCastle.Asn1 return new DerObjectIdentifier(this, branchID); } + public string Id + { + get { return identifier; } + } + /** * Return true if this oid is an extension of the passed in branch, stem. * @param stem the arc or branch that is a possible parent. @@ -115,48 +111,36 @@ namespace Org.BouncyCastle.Asn1 return id.Length > stemId.Length && id[stemId.Length] == '.' && Platform.StartsWith(id, stemId); } - internal DerObjectIdentifier(byte[] contents, bool clone) + public override string ToString() { - this.identifier = MakeOidStringFromBytes(contents); - this.contents = clone ? Arrays.Clone(contents) : contents; + return identifier; } - private void WriteField( - Stream outputStream, - long fieldValue) + protected override bool Asn1Equals(Asn1Object asn1Object) { - byte[] result = new byte[9]; - int pos = 8; - result[pos] = (byte)(fieldValue & 0x7f); - while (fieldValue >= (1L << 7)) - { - fieldValue >>= 7; - result[--pos] = (byte)((fieldValue & 0x7f) | 0x80); - } - outputStream.Write(result, pos, 9 - pos); + DerObjectIdentifier that = asn1Object as DerObjectIdentifier; + return null != that + && this.identifier == that.identifier; } - private void WriteField( - Stream outputStream, - BigInteger fieldValue) + protected override int Asn1GetHashCode() { - int byteCount = (fieldValue.BitLength + 6) / 7; - if (byteCount == 0) - { - outputStream.WriteByte(0); - } - else - { - BigInteger tmpValue = fieldValue; - byte[] tmp = new byte[byteCount]; - for (int i = byteCount-1; i >= 0; i--) - { - tmp[i] = (byte) ((tmpValue.IntValue & 0x7f) | 0x80); - tmpValue = tmpValue.ShiftRight(7); - } - tmp[byteCount-1] &= 0x7f; - outputStream.Write(tmp, 0, tmp.Length); - } + return identifier.GetHashCode(); + } + + internal override bool EncodeConstructed() + { + return false; + } + + internal override int EncodedLength(bool withID) + { + return Asn1OutputStream.GetLengthOfEncodingDL(withID, GetContents().Length); + } + + internal override void Encode(Asn1OutputStream asn1Out, bool withID) + { + asn1Out.WriteEncodingDL(withID, Asn1Tags.ObjectIdentifier, GetContents()); } private void DoOutput(MemoryStream bOut) @@ -169,11 +153,11 @@ namespace Org.BouncyCastle.Asn1 token = tok.NextToken(); if (token.Length <= 18) { - WriteField(bOut, first + Int64.Parse(token)); + Asn1RelativeOid.WriteField(bOut, first + Int64.Parse(token)); } else { - WriteField(bOut, new BigInteger(token).Add(BigInteger.ValueOf(first))); + Asn1RelativeOid.WriteField(bOut, new BigInteger(token).Add(BigInteger.ValueOf(first))); } while (tok.HasMoreTokens) @@ -181,11 +165,11 @@ namespace Org.BouncyCastle.Asn1 token = tok.NextToken(); if (token.Length <= 18) { - WriteField(bOut, Int64.Parse(token)); + Asn1RelativeOid.WriteField(bOut, Int64.Parse(token)); } else { - WriteField(bOut, new BigInteger(token)); + Asn1RelativeOid.WriteField(bOut, new BigInteger(token)); } } } @@ -205,72 +189,21 @@ namespace Org.BouncyCastle.Asn1 } } - internal override bool EncodeConstructed() - { - return false; - } - - internal override int EncodedLength(bool withID) - { - return Asn1OutputStream.GetLengthOfEncodingDL(withID, GetContents().Length); - } - - internal override void Encode(Asn1OutputStream asn1Out, bool withID) - { - asn1Out.WriteEncodingDL(withID, Asn1Tags.ObjectIdentifier, GetContents()); - } - - protected override int Asn1GetHashCode() - { - return identifier.GetHashCode(); - } - - protected override bool Asn1Equals( - Asn1Object asn1Object) - { - DerObjectIdentifier other = asn1Object as DerObjectIdentifier; - - if (other == null) - return false; - - return this.identifier.Equals(other.identifier); - } - - public override string ToString() - { - return identifier; - } - - private static bool IsValidBranchID(string branchID, int start) + internal static DerObjectIdentifier CreatePrimitive(byte[] contents, bool clone) { - int digitCount = 0; + int hashCode = Arrays.GetHashCode(contents); + int first = hashCode & 1023; - int pos = branchID.Length; - while (--pos >= start) + lock (cache) { - char ch = branchID[pos]; - - if (ch == '.') - { - if (0 == digitCount || (digitCount > 1 && branchID[pos + 1] == '0')) - return false; - - digitCount = 0; - } - else if ('0' <= ch && ch <= '9') - { - ++digitCount; - } - else + DerObjectIdentifier entry = cache[first]; + if (entry != null && Arrays.AreEqual(contents, entry.GetContents())) { - return false; + return entry; } - } - - if (0 == digitCount || (digitCount > 1 && branchID[pos + 1] == '0')) - return false; - return true; + return cache[first] = new DerObjectIdentifier(contents, clone); + } } private static bool IsValidIdentifier(string identifier) @@ -282,27 +215,24 @@ namespace Org.BouncyCastle.Asn1 if (first < '0' || first > '2') return false; - return IsValidBranchID(identifier, 2); + return Asn1RelativeOid.IsValidIdentifier(identifier, 2); } - private const long LONG_LIMIT = (long.MaxValue >> 7) - 0x7f; - - private static string MakeOidStringFromBytes( - byte[] bytes) + private static string ParseContents(byte[] contents) { - StringBuilder objId = new StringBuilder(); - long value = 0; - BigInteger bigValue = null; - bool first = true; + StringBuilder objId = new StringBuilder(); + long value = 0; + BigInteger bigValue = null; + bool first = true; - for (int i = 0; i != bytes.Length; i++) + for (int i = 0; i != contents.Length; i++) { - int b = bytes[i]; + int b = contents[i]; - if (value <= LONG_LIMIT) + if (value <= LongLimit) { - value += (b & 0x7f); - if ((b & 0x80) == 0) // end of number reached + value += b & 0x7F; + if ((b & 0x80) == 0) { if (first) { @@ -338,7 +268,7 @@ namespace Org.BouncyCastle.Asn1 { bigValue = BigInteger.ValueOf(value); } - bigValue = bigValue.Or(BigInteger.ValueOf(b & 0x7f)); + bigValue = bigValue.Or(BigInteger.ValueOf(b & 0x7F)); if ((b & 0x80) == 0) { if (first) @@ -362,24 +292,5 @@ namespace Org.BouncyCastle.Asn1 return objId.ToString(); } - - private static readonly DerObjectIdentifier[] cache = new DerObjectIdentifier[1024]; - - internal static DerObjectIdentifier CreatePrimitive(byte[] contents, bool clone) - { - int hashCode = Arrays.GetHashCode(contents); - int first = hashCode & 1023; - - lock (cache) - { - DerObjectIdentifier entry = cache[first]; - if (entry != null && Arrays.AreEqual(contents, entry.GetContents())) - { - return entry; - } - - return cache[first] = new DerObjectIdentifier(contents, clone); - } - } } } diff --git a/crypto/src/asn1/util/Asn1Dump.cs b/crypto/src/asn1/util/Asn1Dump.cs index c82abd5c6..0d3382d00 100644 --- a/crypto/src/asn1/util/Asn1Dump.cs +++ b/crypto/src/asn1/util/Asn1Dump.cs @@ -116,6 +116,10 @@ namespace Org.BouncyCastle.Asn1.Utilities { buf.Append(indent + "ObjectIdentifier(" + ((DerObjectIdentifier)obj).Id + ")" + NewLine); } + else if (obj is Asn1RelativeOid) + { + buf.Append(indent + "RelativeOID(" + ((Asn1RelativeOid)obj).Id + ")" + NewLine); + } else if (obj is DerBoolean) { buf.Append(indent + "Boolean(" + ((DerBoolean)obj).IsTrue + ")" + NewLine); diff --git a/crypto/test/UnitTests.csproj b/crypto/test/UnitTests.csproj index 1945f1367..00f8eb087 100644 --- a/crypto/test/UnitTests.csproj +++ b/crypto/test/UnitTests.csproj @@ -111,6 +111,7 @@ + diff --git a/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs b/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs index 8109d656a..396268f4b 100644 --- a/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs +++ b/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs @@ -36,6 +36,7 @@ namespace Org.BouncyCastle.Asn1.Tests DerNull.Instance, new DerNumericString("123456"), new DerObjectIdentifier("1.1.1.10000.1"), + new Asn1RelativeOid("3.2.0.123456"), new DerOctetString(data), new DerPrintableString("hello world"), new DerSequence(new DerPrintableString("hello world")), diff --git a/crypto/test/src/asn1/test/OIDTest.cs b/crypto/test/src/asn1/test/OIDTest.cs index b0782db04..9a1927a41 100644 --- a/crypto/test/src/asn1/test/OIDTest.cs +++ b/crypto/test/src/asn1/test/OIDTest.cs @@ -1,6 +1,4 @@ using System; -using System.IO; -using System.Text; using NUnit.Framework; @@ -18,17 +16,15 @@ namespace Org.BouncyCastle.Asn1.Tests public class OidTest : SimpleTest { - byte[] req1 = Hex.Decode("0603813403"); - byte[] req2 = Hex.Decode("06082A36FFFFFFDD6311"); + private static readonly byte[] req1 = Hex.Decode("0603813403"); + private static readonly byte[] req2 = Hex.Decode("06082A36FFFFFFDD6311"); public override string Name { get { return "OID"; } } - private void recodeCheck( - string oid, - byte[] enc) + private void RecodeCheck(string oid, byte[] enc) { DerObjectIdentifier o = new DerObjectIdentifier(oid); DerObjectIdentifier encO = (DerObjectIdentifier) Asn1Object.FromByteArray(enc); @@ -46,11 +42,10 @@ namespace Org.BouncyCastle.Asn1.Tests } } - private void validOidCheck( - string oid) + private void CheckValid(string oid) { DerObjectIdentifier o = new DerObjectIdentifier(oid); - o = (DerObjectIdentifier) Asn1Object.FromByteArray(o.GetEncoded()); + o = (DerObjectIdentifier)Asn1Object.FromByteArray(o.GetEncoded()); if (!o.Id.Equals(oid)) { @@ -58,8 +53,7 @@ namespace Org.BouncyCastle.Asn1.Tests } } - private void invalidOidCheck( - string oid) + private void CheckInvalid(string oid) { try { @@ -72,7 +66,7 @@ namespace Org.BouncyCastle.Asn1.Tests } } - private void branchCheck(string stem, string branch) + private void BranchCheck(string stem, string branch) { string expected = stem + "." + branch; string actual = new DerObjectIdentifier(stem).Branch(branch).Id; @@ -83,7 +77,7 @@ namespace Org.BouncyCastle.Asn1.Tests } } - private void onCheck(String stem, String test, bool expected) + private void OnCheck(String stem, String test, bool expected) { if (expected != new DerObjectIdentifier(test).On(new DerObjectIdentifier(stem))) { @@ -93,49 +87,45 @@ namespace Org.BouncyCastle.Asn1.Tests public override void PerformTest() { - recodeCheck("2.100.3", req1); - recodeCheck("1.2.54.34359733987.17", req2); - - validOidCheck(PkcsObjectIdentifiers.Pkcs9AtContentType.Id); - validOidCheck("0.1"); - validOidCheck("1.1.127.32512.8323072.2130706432.545460846592.139637976727552.35747322042253312.9151314442816847872"); - validOidCheck("1.2.123.12345678901.1.1.1"); - validOidCheck("2.25.196556539987194312349856245628873852187.1"); - - invalidOidCheck("0"); - invalidOidCheck("1"); - invalidOidCheck("2"); - invalidOidCheck("3.1"); - invalidOidCheck("..1"); - invalidOidCheck("192.168.1.1"); - invalidOidCheck(".123452"); - invalidOidCheck("1."); - invalidOidCheck("1.345.23.34..234"); - invalidOidCheck("1.345.23.34.234."); - invalidOidCheck(".12.345.77.234"); - invalidOidCheck(".12.345.77.234."); - invalidOidCheck("1.2.3.4.A.5"); - invalidOidCheck("1,2"); - - branchCheck("1.1", "2.2"); - - onCheck("1.1", "1.1", false); - onCheck("1.1", "1.2", false); - onCheck("1.1", "1.2.1", false); - onCheck("1.1", "2.1", false); - onCheck("1.1", "1.11", false); - onCheck("1.12", "1.1.2", false); - onCheck("1.1", "1.1.1", true); - onCheck("1.1", "1.1.2", true); + RecodeCheck("2.100.3", req1); + RecodeCheck("1.2.54.34359733987.17", req2); + + CheckValid(PkcsObjectIdentifiers.Pkcs9AtContentType.Id); + CheckValid("0.1"); + CheckValid("1.1.127.32512.8323072.2130706432.545460846592.139637976727552.35747322042253312.9151314442816847872"); + CheckValid("1.2.123.12345678901.1.1.1"); + CheckValid("2.25.196556539987194312349856245628873852187.1"); + + CheckInvalid("0"); + CheckInvalid("1"); + CheckInvalid("2"); + CheckInvalid("3.1"); + CheckInvalid("..1"); + CheckInvalid("192.168.1.1"); + CheckInvalid(".123452"); + CheckInvalid("1."); + CheckInvalid("1.345.23.34..234"); + CheckInvalid("1.345.23.34.234."); + CheckInvalid(".12.345.77.234"); + CheckInvalid(".12.345.77.234."); + CheckInvalid("1.2.3.4.A.5"); + CheckInvalid("1,2"); + + BranchCheck("1.1", "2.2"); + + OnCheck("1.1", "1.1", false); + OnCheck("1.1", "1.2", false); + OnCheck("1.1", "1.2.1", false); + OnCheck("1.1", "2.1", false); + OnCheck("1.1", "1.11", false); + OnCheck("1.12", "1.1.2", false); + OnCheck("1.1", "1.1.1", true); + OnCheck("1.1", "1.1.2", true); } - public static void Main( - string[] args) + public static void Main(string[] args) { - ITest test = new OidTest(); - ITestResult result = test.Perform(); - - Console.WriteLine(result); + RunTest(new OidTest()); } [Test] diff --git a/crypto/test/src/asn1/test/RegressionTest.cs b/crypto/test/src/asn1/test/RegressionTest.cs index cf10c6c3b..7bc10b079 100644 --- a/crypto/test/src/asn1/test/RegressionTest.cs +++ b/crypto/test/src/asn1/test/RegressionTest.cs @@ -58,7 +58,8 @@ namespace Org.BouncyCastle.Asn1.Tests new ProfessionInfoUnitTest(), new QCStatementUnitTest(), new ReasonFlagsTest(), - new RequestedCertificateUnitTest(), + new RelativeOidTest(), + new RequestedCertificateUnitTest(), new RestrictionUnitTest(), new SemanticsInformationUnitTest(), new SetTest(), diff --git a/crypto/test/src/asn1/test/RelativeOidTest.cs b/crypto/test/src/asn1/test/RelativeOidTest.cs new file mode 100644 index 000000000..e52c1b715 --- /dev/null +++ b/crypto/test/src/asn1/test/RelativeOidTest.cs @@ -0,0 +1,129 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class RelativeOidTest + : SimpleTest + { + private static readonly byte[] req1 = Hex.Decode("0D03813403"); + private static readonly byte[] req2 = Hex.Decode("0D082A36FFFFFFDD6311"); + + public override string Name + { + get { return "RelativeOID"; } + } + + private void RecodeCheck(string oid, byte[] enc) + { + Asn1RelativeOid o = new Asn1RelativeOid(oid); + Asn1RelativeOid encO = (Asn1RelativeOid)Asn1Object.FromByteArray(enc); + + if (!o.Equals(encO)) + { + Fail("relative OID didn't match", o, encO); + } + + byte[] bytes = o.GetDerEncoded(); + + if (!Arrays.AreEqual(bytes, enc)) + { + Fail("failed comparison test", Hex.ToHexString(enc), Hex.ToHexString(bytes)); + } + } + + private void CheckValid(string oid) + { + Asn1RelativeOid o = new Asn1RelativeOid(oid); + o = (Asn1RelativeOid)Asn1Object.FromByteArray(o.GetEncoded()); + + if (!o.Id.Equals(oid)) + { + Fail("failed relative oid check for " + oid); + } + } + + private void CheckInvalid(string oid) + { + try + { + new Asn1RelativeOid(oid); + Fail("failed to catch bad relative oid: " + oid); + } + catch (FormatException) + { + // expected + } + } + + private void BranchCheck(string stem, string branch) + { + string expected = stem + "." + branch; + string actual = new Asn1RelativeOid(stem).Branch(branch).Id; + + if (expected != actual) + { + Fail("failed 'branch' check for " + stem + "/" + branch); + } + } + + public override void PerformTest() + { + RecodeCheck("180.3", req1); + RecodeCheck("42.54.34359733987.17", req2); + + CheckValid("0"); + CheckValid("37"); + CheckValid("0.1"); + CheckValid("1.0"); + CheckValid("1.0.2"); + CheckValid("1.0.20"); + CheckValid("1.0.200"); + CheckValid("1.1.127.32512.8323072.2130706432.545460846592.139637976727552.35747322042253312.9151314442816847872"); + CheckValid("1.2.123.12345678901.1.1.1"); + CheckValid("2.25.196556539987194312349856245628873852187.1"); + CheckValid("3.1"); + CheckValid("37.196556539987194312349856245628873852187.100"); + CheckValid("192.168.1.1"); + + CheckInvalid("00"); + CheckInvalid("0.01"); + CheckInvalid("00.1"); + CheckInvalid("1.00.2"); + CheckInvalid("1.0.02"); + CheckInvalid("1.2.00"); + CheckInvalid(".1"); + CheckInvalid("..1"); + CheckInvalid("3..1"); + CheckInvalid(".123452"); + CheckInvalid("1."); + CheckInvalid("1.345.23.34..234"); + CheckInvalid("1.345.23.34.234."); + CheckInvalid(".12.345.77.234"); + CheckInvalid(".12.345.77.234."); + CheckInvalid("1.2.3.4.A.5"); + CheckInvalid("1,2"); + + BranchCheck("1.1", "2.2"); + } + + public static void Main(string[] args) + { + RunTest(new RelativeOidTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} -- cgit 1.4.1