From f06dc7c2f2e578c77bdb53ff981c578c3fe017eb Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Thu, 1 Aug 2019 20:30:22 +0700 Subject: Rewrite Asn1Sequence/Set to store elements as Asn1Encodable[] --- crypto/src/asn1/Asn1Sequence.cs | 112 ++++++++++++-------------- crypto/src/asn1/Asn1Set.cs | 156 ++++++++++++++----------------------- crypto/src/asn1/BerSequence.cs | 26 +++---- crypto/src/asn1/BerSet.cs | 26 +++---- crypto/src/asn1/DerSequence.cs | 34 +++----- crypto/src/asn1/DerSet.cs | 48 ++++-------- crypto/src/asn1/LazyDERSequence.cs | 22 +++--- crypto/src/asn1/LazyDERSet.cs | 10 ++- 8 files changed, 170 insertions(+), 264 deletions(-) (limited to 'crypto') diff --git a/crypto/src/asn1/Asn1Sequence.cs b/crypto/src/asn1/Asn1Sequence.cs index 849f5e308..854c81590 100644 --- a/crypto/src/asn1/Asn1Sequence.cs +++ b/crypto/src/asn1/Asn1Sequence.cs @@ -10,7 +10,8 @@ namespace Org.BouncyCastle.Asn1 public abstract class Asn1Sequence : Asn1Object, IEnumerable { - private readonly IList seq; + // NOTE: Only non-readonly to support LazyDerSequence + internal Asn1Encodable[] elements; /** * return an Asn1Sequence from the given object. @@ -106,21 +107,38 @@ namespace Org.BouncyCastle.Asn1 throw new ArgumentException("Unknown object in GetInstance: " + Platform.GetTypeName(obj), "obj"); } - protected internal Asn1Sequence( - int capacity) + protected internal Asn1Sequence() { - seq = Platform.CreateArrayList(capacity); + this.elements = Asn1EncodableVector.EmptyElements; } - public virtual IEnumerator GetEnumerator() + protected internal Asn1Sequence(Asn1Encodable element) + { + if (null == element) + throw new ArgumentNullException("element"); + + this.elements = new Asn1Encodable[]{ element }; + } + + protected internal Asn1Sequence(params Asn1Encodable[] elements) { - return seq.GetEnumerator(); + if (Arrays.IsNullOrContainsNull(elements)) + throw new NullReferenceException("'elements' cannot be null, or contain null"); + + this.elements = Asn1EncodableVector.CloneElements(elements); } - [Obsolete("Use GetEnumerator() instead")] - public IEnumerator GetObjects() + protected internal Asn1Sequence(Asn1EncodableVector elementVector) { - return GetEnumerator(); + if (null == elementVector) + throw new ArgumentNullException("elementVector"); + + this.elements = elementVector.TakeElements(); + } + + public virtual IEnumerator GetEnumerator() + { + return elements.GetEnumerator(); } private class Asn1SequenceParserImpl @@ -176,93 +194,59 @@ namespace Org.BouncyCastle.Asn1 */ public virtual Asn1Encodable this[int index] { - get { return (Asn1Encodable) seq[index]; } + get { return elements[index]; } } - [Obsolete("Use 'object[index]' syntax instead")] - public Asn1Encodable GetObjectAt( - int index) - { - return this[index]; - } - - [Obsolete("Use 'Count' property instead")] - public int Size + public virtual int Count { - get { return Count; } + get { return elements.Length; } } - public virtual int Count + public virtual Asn1Encodable[] ToArray() { - get { return seq.Count; } + return Asn1EncodableVector.CloneElements(elements); } protected override int Asn1GetHashCode() { - int hc = Count; + //return Arrays.GetHashCode(elements); + int i = elements.Length; + int hc = i + 1; - foreach (object o in this) + while (--i >= 0) { - hc *= 17; - if (o == null) - { - hc ^= DerNull.Instance.GetHashCode(); - } - else - { - hc ^= o.GetHashCode(); - } + hc *= 257; + hc ^= elements[i].ToAsn1Object().CallAsn1GetHashCode(); } return hc; } - protected override bool Asn1Equals( - Asn1Object asn1Object) + protected override bool Asn1Equals(Asn1Object asn1Object) { - Asn1Sequence other = asn1Object as Asn1Sequence; - - if (other == null) + Asn1Sequence that = asn1Object as Asn1Sequence; + if (null == that) return false; - if (Count != other.Count) + int count = this.Count; + if (that.Count != count) return false; - IEnumerator s1 = GetEnumerator(); - IEnumerator s2 = other.GetEnumerator(); - - while (s1.MoveNext() && s2.MoveNext()) + for (int i = 0; i < count; ++i) { - Asn1Object o1 = GetCurrent(s1).ToAsn1Object(); - Asn1Object o2 = GetCurrent(s2).ToAsn1Object(); + Asn1Object o1 = this.elements[i].ToAsn1Object(); + Asn1Object o2 = that.elements[i].ToAsn1Object(); - if (!o1.Equals(o2)) + if (o1 != o2 && !o1.CallAsn1Equals(o2)) return false; } return true; } - private Asn1Encodable GetCurrent(IEnumerator e) - { - Asn1Encodable encObj = (Asn1Encodable)e.Current; - - // unfortunately null was allowed as a substitute for DER null - if (encObj == null) - return DerNull.Instance; - - return encObj; - } - - protected internal void AddObject( - Asn1Encodable obj) - { - seq.Add(obj); - } - public override string ToString() { - return CollectionUtilities.ToString(seq); + return CollectionUtilities.ToString(elements); } } } diff --git a/crypto/src/asn1/Asn1Set.cs b/crypto/src/asn1/Asn1Set.cs index 7fa072c0d..07605f5e1 100644 --- a/crypto/src/asn1/Asn1Set.cs +++ b/crypto/src/asn1/Asn1Set.cs @@ -16,7 +16,8 @@ namespace Org.BouncyCastle.Asn1 abstract public class Asn1Set : Asn1Object, IEnumerable { - private readonly IList _set; + // NOTE: Only non-readonly to support LazyDerSequence + internal Asn1Encodable[] elements; /** * return an ASN1Set from the given object. @@ -125,21 +126,38 @@ namespace Org.BouncyCastle.Asn1 throw new ArgumentException("Unknown object in GetInstance: " + Platform.GetTypeName(obj), "obj"); } - protected internal Asn1Set( - int capacity) + protected internal Asn1Set() { - _set = Platform.CreateArrayList(capacity); + this.elements = Asn1EncodableVector.EmptyElements; } - public virtual IEnumerator GetEnumerator() + protected internal Asn1Set(Asn1Encodable element) + { + if (null == element) + throw new ArgumentNullException("element"); + + this.elements = new Asn1Encodable[]{ element }; + } + + protected internal Asn1Set(params Asn1Encodable[] elements) { - return _set.GetEnumerator(); + if (Arrays.IsNullOrContainsNull(elements)) + throw new NullReferenceException("'elements' cannot be null, or contain null"); + + this.elements = Asn1EncodableVector.CloneElements(elements); } - [Obsolete("Use GetEnumerator() instead")] - public IEnumerator GetObjects() + protected internal Asn1Set(Asn1EncodableVector elementVector) + { + if (null == elementVector) + throw new ArgumentNullException("elementVector"); + + this.elements = elementVector.TakeElements(); + } + + public virtual IEnumerator GetEnumerator() { - return GetEnumerator(); + return elements.GetEnumerator(); } /** @@ -150,35 +168,17 @@ namespace Org.BouncyCastle.Asn1 */ public virtual Asn1Encodable this[int index] { - get { return (Asn1Encodable) _set[index]; } - } - - [Obsolete("Use 'object[index]' syntax instead")] - public Asn1Encodable GetObjectAt( - int index) - { - return this[index]; - } - - [Obsolete("Use 'Count' property instead")] - public int Size - { - get { return Count; } + get { return elements[index]; } } public virtual int Count { - get { return _set.Count; } + get { return elements.Length; } } public virtual Asn1Encodable[] ToArray() { - Asn1Encodable[] values = new Asn1Encodable[this.Count]; - for (int i = 0; i < this.Count; ++i) - { - values[i] = this[i]; - } - return values; + return Asn1EncodableVector.CloneElements(elements); } private class Asn1SetParserImpl @@ -227,107 +227,67 @@ namespace Org.BouncyCastle.Asn1 protected override int Asn1GetHashCode() { - int hc = Count; + //return Arrays.GetHashCode(elements); + int i = elements.Length; + int hc = i + 1; - foreach (object o in this) + while (--i >= 0) { - hc *= 17; - if (o == null) - { - hc ^= DerNull.Instance.GetHashCode(); - } - else - { - hc ^= o.GetHashCode(); - } + hc *= 257; + hc ^= elements[i].ToAsn1Object().CallAsn1GetHashCode(); } return hc; } - protected override bool Asn1Equals( - Asn1Object asn1Object) + protected override bool Asn1Equals(Asn1Object asn1Object) { - Asn1Set other = asn1Object as Asn1Set; - - if (other == null) + Asn1Set that = asn1Object as Asn1Set; + if (null == that) return false; - if (Count != other.Count) - { + int count = this.Count; + if (that.Count != count) return false; - } - - IEnumerator s1 = GetEnumerator(); - IEnumerator s2 = other.GetEnumerator(); - while (s1.MoveNext() && s2.MoveNext()) + for (int i = 0; i < count; ++i) { - Asn1Object o1 = GetCurrent(s1).ToAsn1Object(); - Asn1Object o2 = GetCurrent(s2).ToAsn1Object(); + Asn1Object o1 = this.elements[i].ToAsn1Object(); + Asn1Object o2 = that.elements[i].ToAsn1Object(); - if (!o1.Equals(o2)) + if (o1 != o2 && !o1.CallAsn1Equals(o2)) return false; } return true; } - private Asn1Encodable GetCurrent(IEnumerator e) - { - Asn1Encodable encObj = (Asn1Encodable)e.Current; - - // unfortunately null was allowed as a substitute for DER null - if (encObj == null) - return DerNull.Instance; - - return encObj; - } - protected internal void Sort() { - if (_set.Count < 2) + if (elements.Length < 2) return; #if PORTABLE - var sorted = _set.Cast() - .Select(a => new { Item = a, Key = a.GetEncoded(Asn1Encodable.Der) }) - .OrderBy(t => t.Key, new DerComparer()) - .Select(t => t.Item) - .ToList(); - - for (int i = 0; i < _set.Count; ++i) - { - _set[i] = sorted[i]; - } + this.elements = elements + .Cast() + .Select(a => new { Item = a, Key = a.GetEncoded(Asn1Encodable.Der) }) + .OrderBy(t => t.Key, new DerComparer()) + .Select(t => t.Item) + .ToArray(); #else - Asn1Encodable[] items = new Asn1Encodable[_set.Count]; - byte[][] keys = new byte[_set.Count][]; - - for (int i = 0; i < _set.Count; ++i) - { - Asn1Encodable item = (Asn1Encodable)_set[i]; - items[i] = item; - keys[i] = item.GetEncoded(Asn1Encodable.Der); - } - - Array.Sort(keys, items, new DerComparer()); - - for (int i = 0; i < _set.Count; ++i) + int count = elements.Length; + byte[][] keys = new byte[count][]; + for (int i = 0; i < count; ++i) { - _set[i] = items[i]; + keys[i] = elements[i].GetEncoded(Asn1Encodable.Der); } + Array.Sort(keys, elements, new DerComparer()); #endif } - protected internal void AddObject(Asn1Encodable obj) - { - _set.Add(obj); - } - public override string ToString() { - return CollectionUtilities.ToString(_set); + return CollectionUtilities.ToString(elements); } #if PORTABLE diff --git a/crypto/src/asn1/BerSequence.cs b/crypto/src/asn1/BerSequence.cs index 70b43fc79..55c93a72e 100644 --- a/crypto/src/asn1/BerSequence.cs +++ b/crypto/src/asn1/BerSequence.cs @@ -5,47 +5,41 @@ namespace Org.BouncyCastle.Asn1 { public static new readonly BerSequence Empty = new BerSequence(); - public static new BerSequence FromVector( - Asn1EncodableVector v) + public static new BerSequence FromVector(Asn1EncodableVector elementVector) { - return v.Count < 1 ? Empty : new BerSequence(v); + return elementVector.Count < 1 ? Empty : new BerSequence(elementVector); } /** * create an empty sequence */ public BerSequence() + : base() { } /** * create a sequence containing one object */ - public BerSequence( - Asn1Encodable obj) - : base(obj) + public BerSequence(Asn1Encodable element) + : base(element) { } - public BerSequence( - params Asn1Encodable[] v) - : base(v) + public BerSequence(params Asn1Encodable[] elements) + : base(elements) { } /** * create a sequence containing a vector of objects. */ - public BerSequence( - Asn1EncodableVector v) - : base(v) + public BerSequence(Asn1EncodableVector elementVector) + : base(elementVector) { } - /* - */ - internal override void Encode( - DerOutputStream derOut) + internal override void Encode(DerOutputStream derOut) { if (derOut is Asn1OutputStream || derOut is BerOutputStream) { diff --git a/crypto/src/asn1/BerSet.cs b/crypto/src/asn1/BerSet.cs index a181e172d..6209e71a8 100644 --- a/crypto/src/asn1/BerSet.cs +++ b/crypto/src/asn1/BerSet.cs @@ -5,48 +5,46 @@ namespace Org.BouncyCastle.Asn1 { public static new readonly BerSet Empty = new BerSet(); - public static new BerSet FromVector( - Asn1EncodableVector v) + public static new BerSet FromVector(Asn1EncodableVector elementVector) { - return v.Count < 1 ? Empty : new BerSet(v); + return elementVector.Count < 1 ? Empty : new BerSet(elementVector); } - internal static new BerSet FromVector( - Asn1EncodableVector v, - bool needsSorting) + internal static new BerSet FromVector(Asn1EncodableVector elementVector, bool needsSorting) { - return v.Count < 1 ? Empty : new BerSet(v, needsSorting); + return elementVector.Count < 1 ? Empty : new BerSet(elementVector, needsSorting); } /** * create an empty sequence */ public BerSet() + : base() { } /** * create a set containing one object */ - public BerSet(Asn1Encodable obj) : base(obj) + public BerSet(Asn1Encodable element) + : base(element) { } /** * create a set containing a vector of objects. */ - public BerSet(Asn1EncodableVector v) : base(v, false) + public BerSet(Asn1EncodableVector elementVector) + : base(elementVector, false) { } - internal BerSet(Asn1EncodableVector v, bool needsSorting) : base(v, needsSorting) + internal BerSet(Asn1EncodableVector elementVector, bool needsSorting) + : base(elementVector, needsSorting) { } - /* - */ - internal override void Encode( - DerOutputStream derOut) + internal override void Encode(DerOutputStream derOut) { if (derOut is Asn1OutputStream || derOut is BerOutputStream) { diff --git a/crypto/src/asn1/DerSequence.cs b/crypto/src/asn1/DerSequence.cs index a76cf2882..823fa869b 100644 --- a/crypto/src/asn1/DerSequence.cs +++ b/crypto/src/asn1/DerSequence.cs @@ -11,51 +11,38 @@ namespace Org.BouncyCastle.Asn1 { public static readonly DerSequence Empty = new DerSequence(); - public static DerSequence FromVector( - Asn1EncodableVector v) + public static DerSequence FromVector(Asn1EncodableVector elementVector) { - return v.Count < 1 ? Empty : new DerSequence(v); + return elementVector.Count < 1 ? Empty : new DerSequence(elementVector); } /** * create an empty sequence */ public DerSequence() - : base(0) + : base() { } /** * create a sequence containing one object */ - public DerSequence( - Asn1Encodable obj) - : base(1) + public DerSequence(Asn1Encodable element) + : base(element) { - AddObject(obj); } - public DerSequence( - params Asn1Encodable[] v) - : base(v.Length) + public DerSequence(params Asn1Encodable[] elements) + : base(elements) { - foreach (Asn1Encodable ae in v) - { - AddObject(ae); - } } /** * create a sequence containing a vector of objects. */ - public DerSequence( - Asn1EncodableVector v) - : base(v.Count) + public DerSequence(Asn1EncodableVector elementVector) + : base(elementVector) { - foreach (Asn1Encodable ae in v) - { - AddObject(ae); - } } /* @@ -66,8 +53,7 @@ namespace Org.BouncyCastle.Asn1 * ASN.1 descriptions given. Rather than just outputing Sequence, * we also have to specify Constructed, and the objects length. */ - internal override void Encode( - DerOutputStream derOut) + internal override void Encode(DerOutputStream derOut) { // TODO Intermediate buffer could be avoided if we could calculate expected length MemoryStream bOut = new MemoryStream(); diff --git a/crypto/src/asn1/DerSet.cs b/crypto/src/asn1/DerSet.cs index 3df1a6766..d4c242778 100644 --- a/crypto/src/asn1/DerSet.cs +++ b/crypto/src/asn1/DerSet.cs @@ -13,68 +13,49 @@ namespace Org.BouncyCastle.Asn1 { public static readonly DerSet Empty = new DerSet(); - public static DerSet FromVector( - Asn1EncodableVector v) + public static DerSet FromVector(Asn1EncodableVector elementVector) { - return v.Count < 1 ? Empty : new DerSet(v); + return elementVector.Count < 1 ? Empty : new DerSet(elementVector); } - internal static DerSet FromVector( - Asn1EncodableVector v, - bool needsSorting) + internal static DerSet FromVector(Asn1EncodableVector elementVector, bool needsSorting) { - return v.Count < 1 ? Empty : new DerSet(v, needsSorting); + return elementVector.Count < 1 ? Empty : new DerSet(elementVector, needsSorting); } /** * create an empty set */ public DerSet() - : base(0) + : base() { } /** * @param obj - a single object that makes up the set. */ - public DerSet( - Asn1Encodable obj) - : base(1) + public DerSet(Asn1Encodable element) + : base(element) { - AddObject(obj); } - public DerSet( - params Asn1Encodable[] v) - : base(v.Length) + public DerSet(params Asn1Encodable[] elements) + : base(elements) { - foreach (Asn1Encodable o in v) - { - AddObject(o); - } - Sort(); } /** * @param v - a vector of objects making up the set. */ - public DerSet( - Asn1EncodableVector v) - : this(v, true) + public DerSet(Asn1EncodableVector elementVector) + : this(elementVector, true) { } - internal DerSet( - Asn1EncodableVector v, - bool needsSorting) - : base(v.Count) + internal DerSet(Asn1EncodableVector elementVector, bool needsSorting) + : base(elementVector) { - foreach (Asn1Encodable o in v) - { - AddObject(o); - } - if (needsSorting) { Sort(); @@ -89,8 +70,7 @@ namespace Org.BouncyCastle.Asn1 * ASN.1 descriptions given. Rather than just outputing Set, * we also have to specify Constructed, and the objects length. */ - internal override void Encode( - DerOutputStream derOut) + internal override void Encode(DerOutputStream derOut) { // TODO Intermediate buffer could be avoided if we could calculate expected length MemoryStream bOut = new MemoryStream(); diff --git a/crypto/src/asn1/LazyDERSequence.cs b/crypto/src/asn1/LazyDERSequence.cs index 7301bc158..8fa7a0792 100644 --- a/crypto/src/asn1/LazyDERSequence.cs +++ b/crypto/src/asn1/LazyDERSequence.cs @@ -19,18 +19,20 @@ namespace Org.BouncyCastle.Asn1 { lock (this) { - if (encoded != null) - { - Asn1InputStream e = new LazyAsn1InputStream(encoded); + if (null != encoded) + { + Asn1EncodableVector v = new Asn1EncodableVector(); + Asn1InputStream e = new LazyAsn1InputStream(encoded); - Asn1Object o; - while ((o = e.ReadObject()) != null) - { - AddObject(o); - } + Asn1Object o; + while ((o = e.ReadObject()) != null) + { + v.Add(o); + } - encoded = null; - } + this.elements = v.TakeElements(); + this.encoded = null; + } } } diff --git a/crypto/src/asn1/LazyDERSet.cs b/crypto/src/asn1/LazyDERSet.cs index e6c9319dd..eac64cbbe 100644 --- a/crypto/src/asn1/LazyDERSet.cs +++ b/crypto/src/asn1/LazyDERSet.cs @@ -21,16 +21,18 @@ namespace Org.BouncyCastle.Asn1 { if (encoded != null) { - Asn1InputStream e = new LazyAsn1InputStream(encoded); + Asn1EncodableVector v = new Asn1EncodableVector(); + Asn1InputStream e = new LazyAsn1InputStream(encoded); Asn1Object o; while ((o = e.ReadObject()) != null) { - AddObject(o); + v.Add(o); } - encoded = null; - } + this.elements = v.TakeElements(); + this.encoded = null; + } } } -- cgit 1.4.1