BERBitString.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Diagnostics;
  5. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1
  6. {
  7. public class BerBitString
  8. : DerBitString
  9. {
  10. private const int DefaultSegmentLimit = 1000;
  11. internal static byte[] FlattenBitStrings(DerBitString[] bitStrings)
  12. {
  13. int count = bitStrings.Length;
  14. switch (count)
  15. {
  16. case 0:
  17. // No bits
  18. return new byte[]{ 0 };
  19. case 1:
  20. return bitStrings[0].contents;
  21. default:
  22. {
  23. int last = count - 1, totalLength = 0;
  24. for (int i = 0; i < last; ++i)
  25. {
  26. byte[] elementContents = bitStrings[i].contents;
  27. if (elementContents[0] != 0)
  28. throw new ArgumentException("only the last nested bitstring can have padding", "bitStrings");
  29. totalLength += elementContents.Length - 1;
  30. }
  31. // Last one can have padding
  32. byte[] lastElementContents = bitStrings[last].contents;
  33. byte padBits = lastElementContents[0];
  34. totalLength += lastElementContents.Length;
  35. byte[] contents = new byte[totalLength];
  36. contents[0] = padBits;
  37. int pos = 1;
  38. for (int i = 0; i < count; ++i)
  39. {
  40. byte[] elementContents = bitStrings[i].contents;
  41. int length = elementContents.Length - 1;
  42. Array.Copy(elementContents, 1, contents, pos, length);
  43. pos += length;
  44. }
  45. Debug.Assert(pos == totalLength);
  46. return contents;
  47. }
  48. }
  49. }
  50. private readonly int segmentLimit;
  51. private readonly DerBitString[] elements;
  52. public BerBitString(byte data, int padBits)
  53. : base(data, padBits)
  54. {
  55. this.elements = null;
  56. this.segmentLimit = DefaultSegmentLimit;
  57. }
  58. public BerBitString(byte[] data)
  59. : this(data, 0)
  60. {
  61. }
  62. public BerBitString(byte[] data, int padBits)
  63. : this(data, padBits, DefaultSegmentLimit)
  64. {
  65. }
  66. public BerBitString(byte[] data, int padBits, int segmentLimit)
  67. : base(data, padBits)
  68. {
  69. this.elements = null;
  70. this.segmentLimit = segmentLimit;
  71. }
  72. public BerBitString(int namedBits)
  73. : base(namedBits)
  74. {
  75. this.elements = null;
  76. this.segmentLimit = DefaultSegmentLimit;
  77. }
  78. public BerBitString(Asn1Encodable obj)
  79. : this(obj.GetDerEncoded(), 0)
  80. {
  81. }
  82. public BerBitString(DerBitString[] elements)
  83. : this(elements, DefaultSegmentLimit)
  84. {
  85. }
  86. public BerBitString(DerBitString[] elements, int segmentLimit)
  87. : base(FlattenBitStrings(elements), false)
  88. {
  89. this.elements = elements;
  90. this.segmentLimit = segmentLimit;
  91. }
  92. internal BerBitString(byte[] contents, bool check)
  93. : base(contents, check)
  94. {
  95. this.elements = null;
  96. this.segmentLimit = DefaultSegmentLimit;
  97. }
  98. internal override IAsn1Encoding GetEncoding(int encoding)
  99. {
  100. if (Asn1OutputStream.EncodingBer != encoding)
  101. return base.GetEncoding(encoding);
  102. if (null == elements)
  103. return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.BitString, contents);
  104. return new ConstructedILEncoding(Asn1Tags.Universal, Asn1Tags.BitString,
  105. Asn1OutputStream.GetContentsEncodings(encoding, elements));
  106. }
  107. internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo)
  108. {
  109. if (Asn1OutputStream.EncodingBer != encoding)
  110. return base.GetEncodingImplicit(encoding, tagClass, tagNo);
  111. if (null == elements)
  112. return new PrimitiveEncoding(tagClass, tagNo, contents);
  113. return new ConstructedILEncoding(tagClass, tagNo,
  114. Asn1OutputStream.GetContentsEncodings(encoding, elements));
  115. }
  116. }
  117. }
  118. #pragma warning restore
  119. #endif