DerInteger.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  6. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1
  7. {
  8. public class DerInteger
  9. : Asn1Object
  10. {
  11. public const string AllowUnsafeProperty = "BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.AllowUnsafeInteger";
  12. internal static bool AllowUnsafe()
  13. {
  14. string allowUnsafeValue = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.GetEnvironmentVariable(AllowUnsafeProperty);
  15. return allowUnsafeValue != null && BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase("true", allowUnsafeValue);
  16. }
  17. internal const int SignExtSigned = -1;
  18. internal const int SignExtUnsigned = 0xFF;
  19. private readonly byte[] bytes;
  20. private readonly int start;
  21. /**
  22. * return an integer from the passed in object
  23. *
  24. * @exception ArgumentException if the object cannot be converted.
  25. */
  26. public static DerInteger GetInstance(
  27. object obj)
  28. {
  29. if (obj == null || obj is DerInteger)
  30. {
  31. return (DerInteger)obj;
  32. }
  33. throw new ArgumentException("illegal object in GetInstance: " + BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.GetTypeName(obj));
  34. }
  35. /**
  36. * return an Integer from a tagged object.
  37. *
  38. * @param obj the tagged object holding the object we want
  39. * @param isExplicit true if the object is meant to be explicitly
  40. * tagged false otherwise.
  41. * @exception ArgumentException if the tagged object cannot
  42. * be converted.
  43. */
  44. public static DerInteger GetInstance(
  45. Asn1TaggedObject obj,
  46. bool isExplicit)
  47. {
  48. if (obj == null)
  49. throw new ArgumentNullException("obj");
  50. Asn1Object o = obj.GetObject();
  51. if (isExplicit || o is DerInteger)
  52. {
  53. return GetInstance(o);
  54. }
  55. return new DerInteger(Asn1OctetString.GetInstance(o).GetOctets());
  56. }
  57. public DerInteger(int value)
  58. {
  59. this.bytes = BigInteger.ValueOf(value).ToByteArray();
  60. this.start = 0;
  61. }
  62. public DerInteger(long value)
  63. {
  64. this.bytes = BigInteger.ValueOf(value).ToByteArray();
  65. this.start = 0;
  66. }
  67. public DerInteger(BigInteger value)
  68. {
  69. if (value == null)
  70. throw new ArgumentNullException("value");
  71. this.bytes = value.ToByteArray();
  72. this.start = 0;
  73. }
  74. public DerInteger(byte[] bytes)
  75. : this(bytes, true)
  76. {
  77. }
  78. internal DerInteger(byte[] bytes, bool clone)
  79. {
  80. if (IsMalformed(bytes))
  81. throw new ArgumentException("malformed integer", "bytes");
  82. this.bytes = clone ? Arrays.Clone(bytes) : bytes;
  83. this.start = SignBytesToSkip(bytes);
  84. }
  85. /**
  86. * in some cases positive values Get crammed into a space,
  87. * that's not quite big enough...
  88. */
  89. public BigInteger PositiveValue
  90. {
  91. get { return new BigInteger(1, bytes); }
  92. }
  93. public BigInteger Value
  94. {
  95. get { return new BigInteger(bytes); }
  96. }
  97. public bool HasValue(int x)
  98. {
  99. return (bytes.Length - start) <= 4
  100. && IntValue(bytes, start, SignExtSigned) == x;
  101. }
  102. public bool HasValue(long x)
  103. {
  104. return (bytes.Length - start) <= 8
  105. && LongValue(bytes, start, SignExtSigned) == x;
  106. }
  107. public bool HasValue(BigInteger x)
  108. {
  109. return null != x
  110. // Fast check to avoid allocation
  111. && IntValue(bytes, start, SignExtSigned) == x.IntValue
  112. && Value.Equals(x);
  113. }
  114. public int IntPositiveValueExact
  115. {
  116. get
  117. {
  118. int count = bytes.Length - start;
  119. if (count > 4 || (count == 4 && 0 != (bytes[start] & 0x80)))
  120. throw new ArithmeticException("ASN.1 Integer out of positive int range");
  121. return IntValue(bytes, start, SignExtUnsigned);
  122. }
  123. }
  124. public int IntValueExact
  125. {
  126. get
  127. {
  128. int count = bytes.Length - start;
  129. if (count > 4)
  130. throw new ArithmeticException("ASN.1 Integer out of int range");
  131. return IntValue(bytes, start, SignExtSigned);
  132. }
  133. }
  134. public long LongValueExact
  135. {
  136. get
  137. {
  138. int count = bytes.Length - start;
  139. if (count > 8)
  140. throw new ArithmeticException("ASN.1 Integer out of long range");
  141. return LongValue(bytes, start, SignExtSigned);
  142. }
  143. }
  144. internal override int EncodedLength(bool withID)
  145. {
  146. return Asn1OutputStream.GetLengthOfEncodingDL(withID, bytes.Length);
  147. }
  148. internal override void Encode(Asn1OutputStream asn1Out, bool withID)
  149. {
  150. asn1Out.WriteEncodingDL(withID, Asn1Tags.Integer, bytes);
  151. }
  152. protected override int Asn1GetHashCode()
  153. {
  154. return Arrays.GetHashCode(bytes);
  155. }
  156. protected override bool Asn1Equals(Asn1Object asn1Object)
  157. {
  158. DerInteger other = asn1Object as DerInteger;
  159. if (other == null)
  160. return false;
  161. return Arrays.AreEqual(this.bytes, other.bytes);
  162. }
  163. public override string ToString()
  164. {
  165. return Value.ToString();
  166. }
  167. internal static int IntValue(byte[] bytes, int start, int signExt)
  168. {
  169. int length = bytes.Length;
  170. int pos = System.Math.Max(start, length - 4);
  171. int val = (sbyte)bytes[pos] & signExt;
  172. while (++pos < length)
  173. {
  174. val = (val << 8) | bytes[pos];
  175. }
  176. return val;
  177. }
  178. internal static long LongValue(byte[] bytes, int start, int signExt)
  179. {
  180. int length = bytes.Length;
  181. int pos = System.Math.Max(start, length - 8);
  182. long val = (sbyte)bytes[pos] & signExt;
  183. while (++pos < length)
  184. {
  185. val = (val << 8) | bytes[pos];
  186. }
  187. return val;
  188. }
  189. /**
  190. * Apply the correct validation for an INTEGER primitive following the BER rules.
  191. *
  192. * @param bytes The raw encoding of the integer.
  193. * @return true if the (in)put fails this validation.
  194. */
  195. internal static bool IsMalformed(byte[] bytes)
  196. {
  197. switch (bytes.Length)
  198. {
  199. case 0:
  200. return true;
  201. case 1:
  202. return false;
  203. default:
  204. return (sbyte)bytes[0] == ((sbyte)bytes[1] >> 7) && !AllowUnsafe();
  205. }
  206. }
  207. internal static int SignBytesToSkip(byte[] bytes)
  208. {
  209. int pos = 0, last = bytes.Length - 1;
  210. while (pos < last
  211. && (sbyte)bytes[pos] == ((sbyte)bytes[pos + 1] >> 7))
  212. {
  213. ++pos;
  214. }
  215. return pos;
  216. }
  217. }
  218. }
  219. #pragma warning restore
  220. #endif