Asn1OutputStream.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.IO;
  5. using System.Diagnostics;
  6. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  7. using System.Buffers.Binary;
  8. using System.Numerics;
  9. #endif
  10. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
  11. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1
  12. {
  13. public class Asn1OutputStream
  14. : FilterStream
  15. {
  16. internal const int EncodingBer = 1;
  17. internal const int EncodingDer = 2;
  18. public static Asn1OutputStream Create(Stream output)
  19. {
  20. return new Asn1OutputStream(output);
  21. }
  22. public static Asn1OutputStream Create(Stream output, string encoding)
  23. {
  24. if (Asn1Encodable.Der.Equals(encoding))
  25. {
  26. return new DerOutputStream(output);
  27. }
  28. else
  29. {
  30. return new Asn1OutputStream(output);
  31. }
  32. }
  33. internal Asn1OutputStream(Stream os)
  34. : base(os)
  35. {
  36. }
  37. public virtual void WriteObject(Asn1Encodable asn1Encodable)
  38. {
  39. if (null == asn1Encodable)
  40. throw new ArgumentNullException("asn1Encodable");
  41. asn1Encodable.ToAsn1Object().GetEncoding(this.Encoding).Encode(this);
  42. FlushInternal();
  43. }
  44. public virtual void WriteObject(Asn1Object asn1Object)
  45. {
  46. if (null == asn1Object)
  47. throw new ArgumentNullException("asn1Object");
  48. asn1Object.GetEncoding(this.Encoding).Encode(this);
  49. FlushInternal();
  50. }
  51. internal void EncodeContents(IAsn1Encoding[] contentsEncodings)
  52. {
  53. for (int i = 0, count = contentsEncodings.Length; i < count; ++i)
  54. {
  55. contentsEncodings[i].Encode(this);
  56. }
  57. }
  58. internal virtual int Encoding
  59. {
  60. get { return EncodingBer; }
  61. }
  62. internal void FlushInternal()
  63. {
  64. // Placeholder to support future internal buffering
  65. }
  66. internal void WriteDL(int dl)
  67. {
  68. if (dl < 128)
  69. {
  70. Debug.Assert(dl >= 0);
  71. WriteByte((byte)dl);
  72. return;
  73. }
  74. #if false && (NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER)
  75. Span<byte> encoding = stackalloc byte[5];
  76. BinaryPrimitives.WriteUInt32BigEndian(encoding[1..], (uint)dl);
  77. int leadingZeroBytes = BitOperations.LeadingZeroCount((uint)dl) / 8;
  78. encoding[leadingZeroBytes] = (byte)(0x84 - leadingZeroBytes);
  79. Write(encoding[leadingZeroBytes..]);
  80. #else
  81. byte[] stack = new byte[5];
  82. int pos = stack.Length;
  83. do
  84. {
  85. stack[--pos] = (byte)dl;
  86. dl >>= 8;
  87. }
  88. while (dl > 0);
  89. int count = stack.Length - pos;
  90. stack[--pos] = (byte)(0x80 | count);
  91. Write(stack, pos, count + 1);
  92. #endif
  93. }
  94. internal void WriteIdentifier(int tagClass, int tagNo)
  95. {
  96. if (tagNo < 31)
  97. {
  98. WriteByte((byte)(tagClass | tagNo));
  99. return;
  100. }
  101. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  102. Span<byte> stack = stackalloc byte[6];
  103. #else
  104. byte[] stack = new byte[6];
  105. #endif
  106. int pos = stack.Length;
  107. stack[--pos] = (byte)(tagNo & 0x7F);
  108. while (tagNo > 127)
  109. {
  110. tagNo >>= 7;
  111. stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
  112. }
  113. stack[--pos] = (byte)(tagClass | 0x1F);
  114. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  115. Write(stack[pos..]);
  116. #else
  117. Write(stack, pos, stack.Length - pos);
  118. #endif
  119. }
  120. internal static IAsn1Encoding[] GetContentsEncodings(int encoding, Asn1Encodable[] elements)
  121. {
  122. int count = elements.Length;
  123. IAsn1Encoding[] contentsEncodings = new IAsn1Encoding[count];
  124. for (int i = 0; i < count; ++i)
  125. {
  126. contentsEncodings[i] = elements[i].ToAsn1Object().GetEncoding(encoding);
  127. }
  128. return contentsEncodings;
  129. }
  130. internal static int GetLengthOfContents(IAsn1Encoding[] contentsEncodings)
  131. {
  132. int contentsLength = 0;
  133. for (int i = 0, count = contentsEncodings.Length; i < count; ++i)
  134. {
  135. contentsLength += contentsEncodings[i].GetLength();
  136. }
  137. return contentsLength;
  138. }
  139. internal static int GetLengthOfDL(int dl)
  140. {
  141. if (dl < 128)
  142. return 1;
  143. int length = 2;
  144. while ((dl >>= 8) > 0)
  145. {
  146. ++length;
  147. }
  148. return length;
  149. }
  150. internal static int GetLengthOfIdentifier(int tagNo)
  151. {
  152. if (tagNo < 31)
  153. return 1;
  154. int length = 2;
  155. while ((tagNo >>= 7) > 0)
  156. {
  157. ++length;
  158. }
  159. return length;
  160. }
  161. }
  162. }
  163. #pragma warning restore
  164. #endif