diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-11-09 23:37:08 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-11-09 23:37:08 +0700 |
commit | 3c034ea8ac68da52b5ff128300b6780549d05bd1 (patch) | |
tree | a3f4572beee014d784560c0ba1282a4000e1a98a /crypto/src/asn1/Asn1Set.cs | |
parent | Fix DER encoding of lazy objects (diff) | |
download | BouncyCastle.NET-ed25519-3c034ea8ac68da52b5ff128300b6780549d05bd1.tar.xz |
Add DLSequence, DLSet for internal use
- improve sorting of sets
Diffstat (limited to 'crypto/src/asn1/Asn1Set.cs')
-rw-r--r-- | crypto/src/asn1/Asn1Set.cs | 129 |
1 files changed, 69 insertions, 60 deletions
diff --git a/crypto/src/asn1/Asn1Set.cs b/crypto/src/asn1/Asn1Set.cs index 453627b7c..b1439be47 100644 --- a/crypto/src/asn1/Asn1Set.cs +++ b/crypto/src/asn1/Asn1Set.cs @@ -13,12 +13,9 @@ using Org.BouncyCastle.Utilities.Collections; namespace Org.BouncyCastle.Asn1 { - abstract public class Asn1Set + public abstract class Asn1Set : Asn1Object, IEnumerable { - // NOTE: Only non-readonly to support LazyDerSet - internal Asn1Encodable[] elements; - /** * return an ASN1Set from the given object. * @@ -63,65 +60,52 @@ namespace Org.BouncyCastle.Asn1 * dealing with implicitly tagged sets you really <b>should</b> * be using this method. * - * @param obj the tagged object. - * @param explicitly true if the object is meant to be explicitly tagged + * @param taggedObject the tagged object. + * @param declaredExplicit true if the object is meant to be explicitly tagged * false otherwise. * @exception ArgumentException if the tagged object cannot * be converted. */ - public static Asn1Set GetInstance( - Asn1TaggedObject obj, - bool explicitly) + public static Asn1Set GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) { - Asn1Object inner = obj.GetObject(); + Asn1Object baseObject = taggedObject.GetObject(); - if (explicitly) + if (declaredExplicit) { - if (!obj.IsExplicit()) + if (!taggedObject.IsExplicit()) throw new ArgumentException("object implicit - explicit expected."); - return (Asn1Set) inner; + return (Asn1Set)baseObject; } - // - // constructed object which appears to be explicitly tagged - // and it's really implicit means we have to add the - // surrounding sequence. - // - if (obj.IsExplicit()) + // If parsed as explicit though declared implicit, it should have been a set of one + if (taggedObject.IsExplicit()) { - return new DerSet(inner); - } + if (taggedObject is BerTaggedObject) + return new BerSet(baseObject); - if (inner is Asn1Set) - { - return (Asn1Set) inner; + return new DLSet(baseObject); } - // - // in this case the parser returns a sequence, convert it - // into a set. - // - if (inner is Asn1Sequence) - { - Asn1EncodableVector v = new Asn1EncodableVector(); - Asn1Sequence s = (Asn1Sequence) inner; + if (baseObject is Asn1Set) + return (Asn1Set)baseObject; - foreach (Asn1Encodable ae in s) - { - v.Add(ae); - } - - // TODO Should be able to construct set directly from sequence? - return new DerSet(v, false); - } + // Parser assumes implicit constructed encodings are sequences + if (baseObject is Asn1Sequence) + return ((Asn1Sequence)baseObject).ToAsn1Set(); - throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj"); + throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(taggedObject), + "taggedObject"); } + // NOTE: Only non-readonly to support LazyDLSet + internal Asn1Encodable[] elements; + internal bool isSorted; + protected internal Asn1Set() { this.elements = Asn1EncodableVector.EmptyElements; + this.isSorted = true; } protected internal Asn1Set(Asn1Encodable element) @@ -130,22 +114,47 @@ namespace Org.BouncyCastle.Asn1 throw new ArgumentNullException("element"); this.elements = new Asn1Encodable[]{ element }; + this.isSorted = true; } - protected internal Asn1Set(params Asn1Encodable[] elements) + protected internal Asn1Set(Asn1Encodable[] elements, bool doSort) { if (Arrays.IsNullOrContainsNull(elements)) throw new NullReferenceException("'elements' cannot be null, or contain null"); - this.elements = Asn1EncodableVector.CloneElements(elements); + Asn1Encodable[] tmp = Asn1EncodableVector.CloneElements(elements); + if (doSort && tmp.Length >= 2) + { + tmp = Sort(tmp); + } + + this.elements = tmp; + this.isSorted = doSort || tmp.Length < 2; } - protected internal Asn1Set(Asn1EncodableVector elementVector) + protected internal Asn1Set(Asn1EncodableVector elementVector, bool doSort) { if (null == elementVector) throw new ArgumentNullException("elementVector"); - this.elements = elementVector.TakeElements(); + Asn1Encodable[] tmp; + if (doSort && elementVector.Count >= 2) + { + tmp = Sort(elementVector.CopyElements()); + } + else + { + tmp = elementVector.TakeElements(); + } + + this.elements = tmp; + this.isSorted = doSort || tmp.Length < 2; + } + + protected internal Asn1Set(bool isSorted, Asn1Encodable[] elements) + { + this.elements = elements; + this.isSorted = isSorted || elements.Length < 2; } public virtual IEnumerator GetEnumerator() @@ -257,15 +266,24 @@ namespace Org.BouncyCastle.Asn1 return true; } - protected internal void Sort() + internal override bool EncodeConstructed() { - // NOTE: Call Count here to 'force' a LazyDerSet - int count = Count; + return true; + } + + public override string ToString() + { + return CollectionUtilities.ToString(elements); + } + + private static Asn1Encodable[] Sort(Asn1Encodable[] elements) + { + int count = elements.Length; if (count < 2) - return; + return elements; #if PORTABLE - this.elements = elements + return elements .Cast<Asn1Encodable>() .Select(a => new { Item = a, Key = a.GetEncoded(Asn1Encodable.Der) }) .OrderBy(t => t.Key, new DerComparer()) @@ -278,19 +296,10 @@ namespace Org.BouncyCastle.Asn1 keys[i] = elements[i].GetEncoded(Der); } Array.Sort(keys, elements, new DerComparer()); + return elements; #endif } - internal override bool EncodeConstructed() - { - return true; - } - - public override string ToString() - { - return CollectionUtilities.ToString(elements); - } - #if PORTABLE private class DerComparer : IComparer<byte[]> |