BerOctetString.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Collections;
  5. using System.Diagnostics;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  7. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1
  8. {
  9. public class BerOctetString
  10. : DerOctetString, IEnumerable
  11. {
  12. private const int DefaultSegmentLimit = 1000;
  13. public static BerOctetString FromSequence(Asn1Sequence seq)
  14. {
  15. int count = seq.Count;
  16. Asn1OctetString[] v = new Asn1OctetString[count];
  17. for (int i = 0; i < count; ++i)
  18. {
  19. v[i] = GetInstance(seq[i]);
  20. }
  21. return new BerOctetString(v);
  22. }
  23. internal static byte[] FlattenOctetStrings(Asn1OctetString[] octetStrings)
  24. {
  25. int count = octetStrings.Length;
  26. switch (count)
  27. {
  28. case 0:
  29. return EmptyOctets;
  30. case 1:
  31. return octetStrings[0].str;
  32. default:
  33. {
  34. int totalOctets = 0;
  35. for (int i = 0; i < count; ++i)
  36. {
  37. totalOctets += octetStrings[i].str.Length;
  38. }
  39. byte[] str = new byte[totalOctets];
  40. int pos = 0;
  41. for (int i = 0; i < count; ++i)
  42. {
  43. byte[] octets = octetStrings[i].str;
  44. Array.Copy(octets, 0, str, pos, octets.Length);
  45. pos += octets.Length;
  46. }
  47. Debug.Assert(pos == totalOctets);
  48. return str;
  49. }
  50. }
  51. }
  52. private static Asn1OctetString[] ToOctetStringArray(IEnumerable e)
  53. {
  54. IList list = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateArrayList(e);
  55. int count = list.Count;
  56. Asn1OctetString[] v = new Asn1OctetString[count];
  57. for (int i = 0; i < count; ++i)
  58. {
  59. v[i] = GetInstance(list[i]);
  60. }
  61. return v;
  62. }
  63. private readonly int segmentLimit;
  64. private readonly Asn1OctetString[] elements;
  65. public BerOctetString(IEnumerable e)
  66. : this(ToOctetStringArray(e))
  67. {
  68. }
  69. public BerOctetString(byte[] str)
  70. : this(str, DefaultSegmentLimit)
  71. {
  72. }
  73. public BerOctetString(Asn1OctetString[] elements)
  74. : this(elements, DefaultSegmentLimit)
  75. {
  76. }
  77. public BerOctetString(byte[] str, int segmentLimit)
  78. : this(str, null, segmentLimit)
  79. {
  80. }
  81. public BerOctetString(Asn1OctetString[] elements, int segmentLimit)
  82. : this(FlattenOctetStrings(elements), elements, segmentLimit)
  83. {
  84. }
  85. private BerOctetString(byte[] octets, Asn1OctetString[] elements, int segmentLimit)
  86. : base(octets)
  87. {
  88. this.elements = elements;
  89. this.segmentLimit = segmentLimit;
  90. }
  91. /**
  92. * return the DER octets that make up this string.
  93. */
  94. public IEnumerator GetEnumerator()
  95. {
  96. if (elements == null)
  97. return new ChunkEnumerator(str, segmentLimit);
  98. return elements.GetEnumerator();
  99. }
  100. public IEnumerator GetObjects()
  101. {
  102. return GetEnumerator();
  103. }
  104. private bool IsConstructed
  105. {
  106. get { return null != elements || str.Length > segmentLimit; }
  107. }
  108. internal override int EncodedLength(bool withID)
  109. {
  110. throw BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateNotImplementedException("BerOctetString.EncodedLength");
  111. // TODO This depends on knowing it's not DER
  112. //if (!IsConstructed)
  113. // return EncodedLength(withID, str.Length);
  114. //int totalLength = withID ? 4 : 3;
  115. //if (null != elements)
  116. //{
  117. // for (int i = 0; i < elements.Length; ++i)
  118. // {
  119. // totalLength += elements[i].EncodedLength(true);
  120. // }
  121. //}
  122. //else
  123. //{
  124. // int fullSegments = str.Length / segmentLimit;
  125. // totalLength += fullSegments * EncodedLength(true, segmentLimit);
  126. // int lastSegmentLength = str.Length - (fullSegments * segmentLimit);
  127. // if (lastSegmentLength > 0)
  128. // {
  129. // totalLength += EncodedLength(true, lastSegmentLength);
  130. // }
  131. //}
  132. //return totalLength;
  133. }
  134. internal override void Encode(Asn1OutputStream asn1Out, bool withID)
  135. {
  136. if (!asn1Out.IsBer || !IsConstructed)
  137. {
  138. base.Encode(asn1Out, withID);
  139. return;
  140. }
  141. asn1Out.WriteIdentifier(withID, Asn1Tags.Constructed | Asn1Tags.OctetString);
  142. asn1Out.WriteByte(0x80);
  143. if (null != elements)
  144. {
  145. asn1Out.WritePrimitives(elements);
  146. }
  147. else
  148. {
  149. int pos = 0;
  150. while (pos < str.Length)
  151. {
  152. int segmentLength = System.Math.Min(str.Length - pos, segmentLimit);
  153. Encode(asn1Out, true, str, pos, segmentLength);
  154. pos += segmentLength;
  155. }
  156. }
  157. asn1Out.WriteByte(0x00);
  158. asn1Out.WriteByte(0x00);
  159. }
  160. private class ChunkEnumerator
  161. : IEnumerator
  162. {
  163. private readonly byte[] octets;
  164. private readonly int segmentLimit;
  165. private DerOctetString currentSegment = null;
  166. private int nextSegmentPos = 0;
  167. internal ChunkEnumerator(byte[] octets, int segmentLimit)
  168. {
  169. this.octets = octets;
  170. this.segmentLimit = segmentLimit;
  171. }
  172. public object Current
  173. {
  174. get
  175. {
  176. if (null == currentSegment)
  177. throw new InvalidOperationException();
  178. return currentSegment;
  179. }
  180. }
  181. public bool MoveNext()
  182. {
  183. if (nextSegmentPos >= octets.Length)
  184. {
  185. this.currentSegment = null;
  186. return false;
  187. }
  188. int length = System.Math.Min(octets.Length - nextSegmentPos, segmentLimit);
  189. byte[] segment = new byte[length];
  190. Array.Copy(octets, nextSegmentPos, segment, 0, length);
  191. this.currentSegment = new DerOctetString(segment);
  192. this.nextSegmentPos += length;
  193. return true;
  194. }
  195. public void Reset()
  196. {
  197. this.currentSegment = null;
  198. this.nextSegmentPos = 0;
  199. }
  200. }
  201. }
  202. }
  203. #pragma warning restore
  204. #endif