Asn1Sequence.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Collections;
  5. using System.IO;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  7. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Collections;
  8. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1
  9. {
  10. public abstract class Asn1Sequence
  11. : Asn1Object, IEnumerable
  12. {
  13. private readonly IList seq;
  14. /**
  15. * return an Asn1Sequence from the given object.
  16. *
  17. * @param obj the object we want converted.
  18. * @exception ArgumentException if the object cannot be converted.
  19. */
  20. public static Asn1Sequence GetInstance(
  21. object obj)
  22. {
  23. if (obj == null || obj is Asn1Sequence)
  24. {
  25. return (Asn1Sequence)obj;
  26. }
  27. else if (obj is Asn1SequenceParser)
  28. {
  29. return Asn1Sequence.GetInstance(((Asn1SequenceParser)obj).ToAsn1Object());
  30. }
  31. else if (obj is byte[])
  32. {
  33. try
  34. {
  35. return Asn1Sequence.GetInstance(FromByteArray((byte[])obj));
  36. }
  37. catch (IOException e)
  38. {
  39. throw new ArgumentException("failed to construct sequence from byte[]: " + e.Message);
  40. }
  41. }
  42. else if (obj is Asn1Encodable)
  43. {
  44. Asn1Object primitive = ((Asn1Encodable)obj).ToAsn1Object();
  45. if (primitive is Asn1Sequence)
  46. {
  47. return (Asn1Sequence)primitive;
  48. }
  49. }
  50. throw new ArgumentException("Unknown object in GetInstance: " + BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.GetTypeName(obj), "obj");
  51. }
  52. /**
  53. * Return an ASN1 sequence from a tagged object. There is a special
  54. * case here, if an object appears to have been explicitly tagged on
  55. * reading but we were expecting it to be implicitly tagged in the
  56. * normal course of events it indicates that we lost the surrounding
  57. * sequence - so we need to add it back (this will happen if the tagged
  58. * object is a sequence that contains other sequences). If you are
  59. * dealing with implicitly tagged sequences you really <b>should</b>
  60. * be using this method.
  61. *
  62. * @param obj the tagged object.
  63. * @param explicitly true if the object is meant to be explicitly tagged,
  64. * false otherwise.
  65. * @exception ArgumentException if the tagged object cannot
  66. * be converted.
  67. */
  68. public static Asn1Sequence GetInstance(
  69. Asn1TaggedObject obj,
  70. bool explicitly)
  71. {
  72. Asn1Object inner = obj.GetObject();
  73. if (explicitly)
  74. {
  75. if (!obj.IsExplicit())
  76. throw new ArgumentException("object implicit - explicit expected.");
  77. return (Asn1Sequence) inner;
  78. }
  79. //
  80. // constructed object which appears to be explicitly tagged
  81. // when it should be implicit means we have to add the
  82. // surrounding sequence.
  83. //
  84. if (obj.IsExplicit())
  85. {
  86. if (obj is BerTaggedObject)
  87. {
  88. return new BerSequence(inner);
  89. }
  90. return new DerSequence(inner);
  91. }
  92. if (inner is Asn1Sequence)
  93. {
  94. return (Asn1Sequence) inner;
  95. }
  96. throw new ArgumentException("Unknown object in GetInstance: " + BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.GetTypeName(obj), "obj");
  97. }
  98. protected internal Asn1Sequence(
  99. int capacity)
  100. {
  101. seq = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList(capacity);
  102. }
  103. public virtual IEnumerator GetEnumerator()
  104. {
  105. return seq.GetEnumerator();
  106. }
  107. [Obsolete("Use GetEnumerator() instead")]
  108. public IEnumerator GetObjects()
  109. {
  110. return GetEnumerator();
  111. }
  112. private class Asn1SequenceParserImpl
  113. : Asn1SequenceParser
  114. {
  115. private readonly Asn1Sequence outer;
  116. private readonly int max;
  117. private int index;
  118. public Asn1SequenceParserImpl(
  119. Asn1Sequence outer)
  120. {
  121. this.outer = outer;
  122. this.max = outer.Count;
  123. }
  124. public IAsn1Convertible ReadObject()
  125. {
  126. if (index == max)
  127. return null;
  128. Asn1Encodable obj = outer[index++];
  129. if (obj is Asn1Sequence)
  130. return ((Asn1Sequence)obj).Parser;
  131. if (obj is Asn1Set)
  132. return ((Asn1Set)obj).Parser;
  133. // NB: Asn1OctetString implements Asn1OctetStringParser directly
  134. // if (obj is Asn1OctetString)
  135. // return ((Asn1OctetString)obj).Parser;
  136. return obj;
  137. }
  138. public Asn1Object ToAsn1Object()
  139. {
  140. return outer;
  141. }
  142. }
  143. public virtual Asn1SequenceParser Parser
  144. {
  145. get { return new Asn1SequenceParserImpl(this); }
  146. }
  147. /**
  148. * return the object at the sequence position indicated by index.
  149. *
  150. * @param index the sequence number (starting at zero) of the object
  151. * @return the object at the sequence position indicated by index.
  152. */
  153. public virtual Asn1Encodable this[int index]
  154. {
  155. get { return (Asn1Encodable) seq[index]; }
  156. }
  157. [Obsolete("Use 'object[index]' syntax instead")]
  158. public Asn1Encodable GetObjectAt(
  159. int index)
  160. {
  161. return this[index];
  162. }
  163. [Obsolete("Use 'Count' property instead")]
  164. public int Size
  165. {
  166. get { return Count; }
  167. }
  168. public virtual int Count
  169. {
  170. get { return seq.Count; }
  171. }
  172. protected override int Asn1GetHashCode()
  173. {
  174. int hc = Count;
  175. foreach (object o in this)
  176. {
  177. hc *= 17;
  178. if (o == null)
  179. {
  180. hc ^= DerNull.Instance.GetHashCode();
  181. }
  182. else
  183. {
  184. hc ^= o.GetHashCode();
  185. }
  186. }
  187. return hc;
  188. }
  189. protected override bool Asn1Equals(
  190. Asn1Object asn1Object)
  191. {
  192. Asn1Sequence other = asn1Object as Asn1Sequence;
  193. if (other == null)
  194. return false;
  195. if (Count != other.Count)
  196. return false;
  197. IEnumerator s1 = GetEnumerator();
  198. IEnumerator s2 = other.GetEnumerator();
  199. while (s1.MoveNext() && s2.MoveNext())
  200. {
  201. Asn1Object o1 = GetCurrent(s1).ToAsn1Object();
  202. Asn1Object o2 = GetCurrent(s2).ToAsn1Object();
  203. if (!o1.Equals(o2))
  204. return false;
  205. }
  206. return true;
  207. }
  208. private Asn1Encodable GetCurrent(IEnumerator e)
  209. {
  210. Asn1Encodable encObj = (Asn1Encodable)e.Current;
  211. // unfortunately null was allowed as a substitute for DER null
  212. if (encObj == null)
  213. return DerNull.Instance;
  214. return encObj;
  215. }
  216. protected internal void AddObject(
  217. Asn1Encodable obj)
  218. {
  219. seq.Add(obj);
  220. }
  221. public override string ToString()
  222. {
  223. return CollectionUtilities.ToString(seq);
  224. }
  225. }
  226. }
  227. #pragma warning restore
  228. #endif