Asn1Sequence.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  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.IO;
  6. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  7. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
  8. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1
  9. {
  10. public abstract class Asn1Sequence
  11. : Asn1Object, IEnumerable<Asn1Encodable>
  12. {
  13. internal class Meta : Asn1UniversalType
  14. {
  15. internal static readonly Asn1UniversalType Instance = new Meta();
  16. private Meta() : base(typeof(Asn1Sequence), Asn1Tags.Sequence) {}
  17. internal override Asn1Object FromImplicitConstructed(Asn1Sequence sequence)
  18. {
  19. return sequence;
  20. }
  21. }
  22. /**
  23. * return an Asn1Sequence from the given object.
  24. *
  25. * @param obj the object we want converted.
  26. * @exception ArgumentException if the object cannot be converted.
  27. */
  28. public static Asn1Sequence GetInstance(object obj)
  29. {
  30. if (obj == null)
  31. return null;
  32. if (obj is Asn1Sequence asn1Sequence)
  33. return asn1Sequence;
  34. if (obj is IAsn1Convertible asn1Convertible)
  35. {
  36. Asn1Object asn1Object = asn1Convertible.ToAsn1Object();
  37. if (asn1Object is Asn1Sequence converted)
  38. return converted;
  39. }
  40. else if (obj is byte[] bytes)
  41. {
  42. try
  43. {
  44. return (Asn1Sequence)Meta.Instance.FromByteArray(bytes);
  45. }
  46. catch (IOException e)
  47. {
  48. throw new ArgumentException("failed to construct sequence from byte[]: " + e.Message);
  49. }
  50. }
  51. throw new ArgumentException("illegal object in GetInstance: " + Org.BouncyCastle.Utilities.Platform.GetTypeName(obj), "obj");
  52. }
  53. /**
  54. * Return an ASN1 sequence from a tagged object. There is a special
  55. * case here, if an object appears to have been explicitly tagged on
  56. * reading but we were expecting it to be implicitly tagged in the
  57. * normal course of events it indicates that we lost the surrounding
  58. * sequence - so we need to add it back (this will happen if the tagged
  59. * object is a sequence that contains other sequences). If you are
  60. * dealing with implicitly tagged sequences you really <b>should</b>
  61. * be using this method.
  62. *
  63. * @param taggedObject the tagged object.
  64. * @param declaredExplicit true if the object is meant to be explicitly tagged, false otherwise.
  65. * @exception ArgumentException if the tagged object cannot be converted.
  66. */
  67. public static Asn1Sequence GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
  68. {
  69. return (Asn1Sequence)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
  70. }
  71. // NOTE: Only non-readonly to support LazyDLSequence
  72. internal Asn1Encodable[] elements;
  73. protected internal Asn1Sequence()
  74. {
  75. this.elements = Asn1EncodableVector.EmptyElements;
  76. }
  77. protected internal Asn1Sequence(Asn1Encodable element)
  78. {
  79. if (null == element)
  80. throw new ArgumentNullException(nameof(element));
  81. this.elements = new Asn1Encodable[]{ element };
  82. }
  83. protected internal Asn1Sequence(Asn1Encodable element1, Asn1Encodable element2)
  84. {
  85. if (null == element1)
  86. throw new ArgumentNullException(nameof(element1));
  87. if (null == element2)
  88. throw new ArgumentNullException(nameof(element2));
  89. this.elements = new Asn1Encodable[]{ element1, element2 };
  90. }
  91. protected internal Asn1Sequence(params Asn1Encodable[] elements)
  92. {
  93. if (Arrays.IsNullOrContainsNull(elements))
  94. throw new NullReferenceException("'elements' cannot be null, or contain null");
  95. this.elements = Asn1EncodableVector.CloneElements(elements);
  96. }
  97. internal Asn1Sequence(Asn1Encodable[] elements, bool clone)
  98. {
  99. this.elements = clone ? Asn1EncodableVector.CloneElements(elements) : elements;
  100. }
  101. protected internal Asn1Sequence(Asn1EncodableVector elementVector)
  102. {
  103. if (null == elementVector)
  104. throw new ArgumentNullException("elementVector");
  105. this.elements = elementVector.TakeElements();
  106. }
  107. System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
  108. {
  109. return GetEnumerator();
  110. }
  111. public virtual IEnumerator<Asn1Encodable> GetEnumerator()
  112. {
  113. IEnumerable<Asn1Encodable> e = elements;
  114. return e.GetEnumerator();
  115. }
  116. private class Asn1SequenceParserImpl
  117. : Asn1SequenceParser
  118. {
  119. private readonly Asn1Sequence outer;
  120. private readonly int max;
  121. private int index;
  122. public Asn1SequenceParserImpl(
  123. Asn1Sequence outer)
  124. {
  125. this.outer = outer;
  126. // NOTE: Call Count here to 'force' a LazyDerSequence
  127. this.max = outer.Count;
  128. }
  129. public IAsn1Convertible ReadObject()
  130. {
  131. if (index == max)
  132. return null;
  133. Asn1Encodable obj = outer[index++];
  134. if (obj is Asn1Sequence)
  135. return ((Asn1Sequence)obj).Parser;
  136. if (obj is Asn1Set)
  137. return ((Asn1Set)obj).Parser;
  138. // NB: Asn1OctetString implements Asn1OctetStringParser directly
  139. // if (obj is Asn1OctetString)
  140. // return ((Asn1OctetString)obj).Parser;
  141. return obj;
  142. }
  143. public Asn1Object ToAsn1Object()
  144. {
  145. return outer;
  146. }
  147. }
  148. public virtual Asn1SequenceParser Parser
  149. {
  150. get { return new Asn1SequenceParserImpl(this); }
  151. }
  152. /**
  153. * return the object at the sequence position indicated by index.
  154. *
  155. * @param index the sequence number (starting at zero) of the object
  156. * @return the object at the sequence position indicated by index.
  157. */
  158. public virtual Asn1Encodable this[int index]
  159. {
  160. get { return elements[index]; }
  161. }
  162. public virtual int Count
  163. {
  164. get { return elements.Length; }
  165. }
  166. public virtual T[] MapElements<T>(Func<Asn1Encodable, T> func)
  167. {
  168. // NOTE: Call Count here to 'force' a LazyDerSequence
  169. int count = Count;
  170. T[] result = new T[count];
  171. for (int i = 0; i < count; ++i)
  172. {
  173. result[i] = func(elements[i]);
  174. }
  175. return result;
  176. }
  177. public virtual Asn1Encodable[] ToArray()
  178. {
  179. return Asn1EncodableVector.CloneElements(elements);
  180. }
  181. protected override int Asn1GetHashCode()
  182. {
  183. // NOTE: Call Count here to 'force' a LazyDerSequence
  184. int i = Count;
  185. int hc = i + 1;
  186. while (--i >= 0)
  187. {
  188. hc *= 257;
  189. hc ^= elements[i].ToAsn1Object().CallAsn1GetHashCode();
  190. }
  191. return hc;
  192. }
  193. protected override bool Asn1Equals(Asn1Object asn1Object)
  194. {
  195. Asn1Sequence that = asn1Object as Asn1Sequence;
  196. if (null == that)
  197. return false;
  198. // NOTE: Call Count here (on both) to 'force' a LazyDerSequence
  199. int count = this.Count;
  200. if (that.Count != count)
  201. return false;
  202. for (int i = 0; i < count; ++i)
  203. {
  204. Asn1Object o1 = this.elements[i].ToAsn1Object();
  205. Asn1Object o2 = that.elements[i].ToAsn1Object();
  206. if (!o1.Equals(o2))
  207. return false;
  208. }
  209. return true;
  210. }
  211. public override string ToString()
  212. {
  213. return CollectionUtilities.ToString(elements);
  214. }
  215. // TODO[asn1] Preferably return an Asn1BitString[] (doesn't exist yet)
  216. internal DerBitString[] GetConstructedBitStrings()
  217. {
  218. return MapElements(DerBitString.GetInstance);
  219. }
  220. internal Asn1OctetString[] GetConstructedOctetStrings()
  221. {
  222. return MapElements(Asn1OctetString.GetInstance);
  223. }
  224. // TODO[asn1] Preferably return an Asn1BitString (doesn't exist yet)
  225. internal abstract DerBitString ToAsn1BitString();
  226. // TODO[asn1] Preferably return an Asn1External (doesn't exist yet)
  227. internal abstract DerExternal ToAsn1External();
  228. internal abstract Asn1OctetString ToAsn1OctetString();
  229. internal abstract Asn1Set ToAsn1Set();
  230. }
  231. }
  232. #pragma warning restore
  233. #endif