Asn1Set.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.IO;
  7. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  8. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
  9. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1
  10. {
  11. public abstract class Asn1Set
  12. : Asn1Object, IEnumerable<Asn1Encodable>
  13. {
  14. internal class Meta : Asn1UniversalType
  15. {
  16. internal static readonly Asn1UniversalType Instance = new Meta();
  17. private Meta() : base(typeof(Asn1Set), Asn1Tags.Set) {}
  18. internal override Asn1Object FromImplicitConstructed(Asn1Sequence sequence)
  19. {
  20. return sequence.ToAsn1Set();
  21. }
  22. }
  23. /**
  24. * return an ASN1Set from the given object.
  25. *
  26. * @param obj the object we want converted.
  27. * @exception ArgumentException if the object cannot be converted.
  28. */
  29. public static Asn1Set GetInstance(object obj)
  30. {
  31. if (obj == null)
  32. return null;
  33. if (obj is Asn1Set asn1Set)
  34. return asn1Set;
  35. if (obj is IAsn1Convertible asn1Convertible)
  36. {
  37. Asn1Object asn1Object = asn1Convertible.ToAsn1Object();
  38. if (asn1Object is Asn1Set converted)
  39. return converted;
  40. }
  41. else if (obj is byte[] bytes)
  42. {
  43. try
  44. {
  45. return (Asn1Set)Meta.Instance.FromByteArray(bytes);
  46. }
  47. catch (IOException e)
  48. {
  49. throw new ArgumentException("failed to construct set from byte[]: " + e.Message);
  50. }
  51. }
  52. throw new ArgumentException("illegal object in GetInstance: " + Org.BouncyCastle.Utilities.Platform.GetTypeName(obj), "obj");
  53. }
  54. /**
  55. * Return an ASN1 set from a tagged object. There is a special
  56. * case here, if an object appears to have been explicitly tagged on
  57. * reading but we were expecting it to be implicitly tagged in the
  58. * normal course of events it indicates that we lost the surrounding
  59. * set - so we need to add it back (this will happen if the tagged
  60. * object is a sequence that contains other sequences). If you are
  61. * dealing with implicitly tagged sets you really <b>should</b>
  62. * be using this method.
  63. *
  64. * @param taggedObject the tagged object.
  65. * @param declaredExplicit true if the object is meant to be explicitly tagged false otherwise.
  66. * @exception ArgumentException if the tagged object cannot be converted.
  67. */
  68. public static Asn1Set GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
  69. {
  70. return (Asn1Set)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
  71. }
  72. // NOTE: Only non-readonly to support LazyDLSet
  73. internal Asn1Encodable[] elements;
  74. internal bool isSorted;
  75. protected internal Asn1Set()
  76. {
  77. this.elements = Asn1EncodableVector.EmptyElements;
  78. this.isSorted = true;
  79. }
  80. protected internal Asn1Set(Asn1Encodable element)
  81. {
  82. if (null == element)
  83. throw new ArgumentNullException("element");
  84. this.elements = new Asn1Encodable[]{ element };
  85. this.isSorted = true;
  86. }
  87. protected internal Asn1Set(Asn1Encodable[] elements, bool doSort)
  88. {
  89. if (Arrays.IsNullOrContainsNull(elements))
  90. throw new NullReferenceException("'elements' cannot be null, or contain null");
  91. Asn1Encodable[] tmp = Asn1EncodableVector.CloneElements(elements);
  92. if (doSort && tmp.Length >= 2)
  93. {
  94. tmp = Sort(tmp);
  95. }
  96. this.elements = tmp;
  97. this.isSorted = doSort || tmp.Length < 2;
  98. }
  99. protected internal Asn1Set(Asn1EncodableVector elementVector, bool doSort)
  100. {
  101. if (null == elementVector)
  102. throw new ArgumentNullException("elementVector");
  103. Asn1Encodable[] tmp;
  104. if (doSort && elementVector.Count >= 2)
  105. {
  106. tmp = Sort(elementVector.CopyElements());
  107. }
  108. else
  109. {
  110. tmp = elementVector.TakeElements();
  111. }
  112. this.elements = tmp;
  113. this.isSorted = doSort || tmp.Length < 2;
  114. }
  115. protected internal Asn1Set(bool isSorted, Asn1Encodable[] elements)
  116. {
  117. this.elements = elements;
  118. this.isSorted = isSorted || elements.Length < 2;
  119. }
  120. System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
  121. {
  122. return GetEnumerator();
  123. }
  124. public virtual IEnumerator<Asn1Encodable> GetEnumerator()
  125. {
  126. IEnumerable<Asn1Encodable> e = elements;
  127. return e.GetEnumerator();
  128. }
  129. /**
  130. * return the object at the set position indicated by index.
  131. *
  132. * @param index the set number (starting at zero) of the object
  133. * @return the object at the set position indicated by index.
  134. */
  135. public virtual Asn1Encodable this[int index]
  136. {
  137. get { return elements[index]; }
  138. }
  139. public virtual int Count
  140. {
  141. get { return elements.Length; }
  142. }
  143. public virtual T[] MapElements<T>(Func<Asn1Encodable, T> func)
  144. {
  145. // NOTE: Call Count here to 'force' a LazyDerSet
  146. int count = Count;
  147. T[] result = new T[count];
  148. for (int i = 0; i < count; ++i)
  149. {
  150. result[i] = func(elements[i]);
  151. }
  152. return result;
  153. }
  154. public virtual Asn1Encodable[] ToArray()
  155. {
  156. return Asn1EncodableVector.CloneElements(elements);
  157. }
  158. private class Asn1SetParserImpl
  159. : Asn1SetParser
  160. {
  161. private readonly Asn1Set outer;
  162. private readonly int max;
  163. private int index;
  164. public Asn1SetParserImpl(
  165. Asn1Set outer)
  166. {
  167. this.outer = outer;
  168. // NOTE: Call Count here to 'force' a LazyDerSet
  169. this.max = outer.Count;
  170. }
  171. public IAsn1Convertible ReadObject()
  172. {
  173. if (index == max)
  174. return null;
  175. Asn1Encodable obj = outer[index++];
  176. if (obj is Asn1Sequence)
  177. return ((Asn1Sequence)obj).Parser;
  178. if (obj is Asn1Set)
  179. return ((Asn1Set)obj).Parser;
  180. // NB: Asn1OctetString implements Asn1OctetStringParser directly
  181. // if (obj is Asn1OctetString)
  182. // return ((Asn1OctetString)obj).Parser;
  183. return obj;
  184. }
  185. public virtual Asn1Object ToAsn1Object()
  186. {
  187. return outer;
  188. }
  189. }
  190. public Asn1SetParser Parser
  191. {
  192. get { return new Asn1SetParserImpl(this); }
  193. }
  194. protected override int Asn1GetHashCode()
  195. {
  196. // NOTE: Call Count here to 'force' a LazyDerSet
  197. int i = Count;
  198. int hc = i + 1;
  199. while (--i >= 0)
  200. {
  201. hc *= 257;
  202. hc ^= elements[i].ToAsn1Object().CallAsn1GetHashCode();
  203. }
  204. return hc;
  205. }
  206. protected override bool Asn1Equals(Asn1Object asn1Object)
  207. {
  208. Asn1Set that = asn1Object as Asn1Set;
  209. if (null == that)
  210. return false;
  211. // NOTE: Call Count here (on both) to 'force' a LazyDerSet
  212. int count = this.Count;
  213. if (that.Count != count)
  214. return false;
  215. for (int i = 0; i < count; ++i)
  216. {
  217. Asn1Object o1 = this.elements[i].ToAsn1Object();
  218. Asn1Object o2 = that.elements[i].ToAsn1Object();
  219. if (!o1.Equals(o2))
  220. return false;
  221. }
  222. return true;
  223. }
  224. public override string ToString()
  225. {
  226. return CollectionUtilities.ToString(elements);
  227. }
  228. internal static Asn1Encodable[] Sort(Asn1Encodable[] elements)
  229. {
  230. int count = elements.Length;
  231. if (count < 2)
  232. return elements;
  233. byte[][] keys = new byte[count][];
  234. for (int i = 0; i < count; ++i)
  235. {
  236. keys[i] = elements[i].GetEncoded(Der);
  237. }
  238. Array.Sort(keys, elements, new DerComparer());
  239. return elements;
  240. }
  241. private class DerComparer
  242. : IComparer<byte[]>
  243. {
  244. public int Compare(byte[] a, byte[] b)
  245. {
  246. Debug.Assert(a.Length >= 2 && b.Length >= 2);
  247. /*
  248. * NOTE: Set elements in DER encodings are ordered first according to their tags (class and
  249. * number); the CONSTRUCTED bit is not part of the tag.
  250. *
  251. * For SET-OF, this is unimportant. All elements have the same tag and DER requires them to
  252. * either all be in constructed form or all in primitive form, according to that tag. The
  253. * elements are effectively ordered according to their content octets.
  254. *
  255. * For SET, the elements will have distinct tags, and each will be in constructed or
  256. * primitive form accordingly. Failing to ignore the CONSTRUCTED bit could therefore lead to
  257. * ordering inversions.
  258. */
  259. int a0 = a[0] & ~Asn1Tags.Constructed;
  260. int b0 = b[0] & ~Asn1Tags.Constructed;
  261. if (a0 != b0)
  262. return a0 < b0 ? -1 : 1;
  263. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  264. int compareLength = System.Math.Min(a.Length, b.Length) - 1;
  265. return a.AsSpan(1, compareLength).SequenceCompareTo(b.AsSpan(1, compareLength));
  266. #else
  267. int len = System.Math.Min(a.Length, b.Length);
  268. for (int i = 1; i < len; ++i)
  269. {
  270. byte ai = a[i], bi = b[i];
  271. if (ai != bi)
  272. return ai < bi ? -1 : 1;
  273. }
  274. Debug.Assert(a.Length == b.Length);
  275. return 0;
  276. #endif
  277. }
  278. }
  279. }
  280. }
  281. #pragma warning restore
  282. #endif