DerGeneralizedTime.cs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. using System.Globalization;
  4. using System.Text;
  5. using Org.BouncyCastle.Utilities;
  6. namespace Org.BouncyCastle.Asn1
  7. {
  8. /**
  9. * Generalized time object.
  10. */
  11. public class DerGeneralizedTime
  12. : Asn1Object
  13. {
  14. private readonly string time;
  15. /**
  16. * return a generalized time from the passed in object
  17. *
  18. * @exception ArgumentException if the object cannot be converted.
  19. */
  20. public static DerGeneralizedTime GetInstance(
  21. object obj)
  22. {
  23. if (obj == null || obj is DerGeneralizedTime)
  24. {
  25. return (DerGeneralizedTime)obj;
  26. }
  27. throw new ArgumentException("illegal object in GetInstance: " + Org.BouncyCastle.Utilities.Platform.GetTypeName(obj), "obj");
  28. }
  29. /**
  30. * return a Generalized Time object from a tagged object.
  31. *
  32. * @param obj the tagged object holding the object we want
  33. * @param explicitly true if the object is meant to be explicitly
  34. * tagged false otherwise.
  35. * @exception ArgumentException if the tagged object cannot
  36. * be converted.
  37. */
  38. public static DerGeneralizedTime GetInstance(
  39. Asn1TaggedObject obj,
  40. bool isExplicit)
  41. {
  42. Asn1Object o = obj.GetObject();
  43. if (isExplicit || o is DerGeneralizedTime)
  44. {
  45. return GetInstance(o);
  46. }
  47. return new DerGeneralizedTime(((Asn1OctetString)o).GetOctets());
  48. }
  49. /**
  50. * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
  51. * for local time, or Z+-HHMM on the end, for difference between local
  52. * time and UTC time. The fractional second amount f must consist of at
  53. * least one number with trailing zeroes removed.
  54. *
  55. * @param time the time string.
  56. * @exception ArgumentException if string is an illegal format.
  57. */
  58. public DerGeneralizedTime(
  59. string time)
  60. {
  61. this.time = time;
  62. try
  63. {
  64. ToDateTime();
  65. }
  66. catch (FormatException e)
  67. {
  68. throw new ArgumentException("invalid date string: " + e.Message);
  69. }
  70. }
  71. /**
  72. * base constructor from a local time object
  73. */
  74. public DerGeneralizedTime(
  75. DateTime time)
  76. {
  77. #if PORTABLE || NETFX_CORE
  78. this.time = time.ToUniversalTime().ToString(@"yyyyMMddHHmmss\Z");
  79. #else
  80. this.time = time.ToString(@"yyyyMMddHHmmss\Z");
  81. #endif
  82. }
  83. internal DerGeneralizedTime(
  84. byte[] bytes)
  85. {
  86. //
  87. // explicitly convert to characters
  88. //
  89. this.time = Strings.FromAsciiByteArray(bytes);
  90. }
  91. /**
  92. * Return the time.
  93. * @return The time string as it appeared in the encoded object.
  94. */
  95. public string TimeString
  96. {
  97. get { return time; }
  98. }
  99. /**
  100. * return the time - always in the form of
  101. * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
  102. * <p>
  103. * Normally in a certificate we would expect "Z" rather than "GMT",
  104. * however adding the "GMT" means we can just use:
  105. * <pre>
  106. * dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
  107. * </pre>
  108. * To read in the time and Get a date which is compatible with our local
  109. * time zone.</p>
  110. */
  111. public string GetTime()
  112. {
  113. //
  114. // standardise the format.
  115. //
  116. if (time[time.Length - 1] == 'Z')
  117. {
  118. return time.Substring(0, time.Length - 1) + "GMT+00:00";
  119. }
  120. else
  121. {
  122. int signPos = time.Length - 5;
  123. char sign = time[signPos];
  124. if (sign == '-' || sign == '+')
  125. {
  126. return time.Substring(0, signPos)
  127. + "GMT"
  128. + time.Substring(signPos, 3)
  129. + ":"
  130. + time.Substring(signPos + 3);
  131. }
  132. else
  133. {
  134. signPos = time.Length - 3;
  135. sign = time[signPos];
  136. if (sign == '-' || sign == '+')
  137. {
  138. return time.Substring(0, signPos)
  139. + "GMT"
  140. + time.Substring(signPos)
  141. + ":00";
  142. }
  143. }
  144. }
  145. return time + CalculateGmtOffset();
  146. }
  147. private string CalculateGmtOffset()
  148. {
  149. char sign = '+';
  150. DateTime time = ToDateTime();
  151. #if true //SILVERLIGHT || PORTABLE || NETFX_CORE
  152. long offset = time.Ticks - time.ToUniversalTime().Ticks;
  153. if (offset < 0)
  154. {
  155. sign = '-';
  156. offset = -offset;
  157. }
  158. int hours = (int)(offset / TimeSpan.TicksPerHour);
  159. int minutes = (int)(offset / TimeSpan.TicksPerMinute) % 60;
  160. #else
  161. // Note: GetUtcOffset incorporates Daylight Savings offset
  162. TimeSpan offset = TimeZone.CurrentTimeZone.GetUtcOffset(time);
  163. if (offset.CompareTo(TimeSpan.Zero) < 0)
  164. {
  165. sign = '-';
  166. offset = offset.Duration();
  167. }
  168. int hours = offset.Hours;
  169. int minutes = offset.Minutes;
  170. #endif
  171. return "GMT" + sign + Convert(hours) + ":" + Convert(minutes);
  172. }
  173. private static string Convert(
  174. int time)
  175. {
  176. if (time < 10)
  177. {
  178. return "0" + time;
  179. }
  180. return time.ToString();
  181. }
  182. public DateTime ToDateTime()
  183. {
  184. string formatStr;
  185. string d = time;
  186. bool makeUniversal = false;
  187. if (Org.BouncyCastle.Utilities.Platform.EndsWith(d, "Z"))
  188. {
  189. if (HasFractionalSeconds)
  190. {
  191. int fCount = d.Length - d.IndexOf('.') - 2;
  192. formatStr = @"yyyyMMddHHmmss." + FString(fCount) + @"\Z";
  193. }
  194. else
  195. {
  196. formatStr = @"yyyyMMddHHmmss\Z";
  197. }
  198. }
  199. else if (time.IndexOf('-') > 0 || time.IndexOf('+') > 0)
  200. {
  201. d = GetTime();
  202. makeUniversal = true;
  203. if (HasFractionalSeconds)
  204. {
  205. int fCount = Org.BouncyCastle.Utilities.Platform.IndexOf(d, "GMT") - 1 - d.IndexOf('.');
  206. formatStr = @"yyyyMMddHHmmss." + FString(fCount) + @"'GMT'zzz";
  207. }
  208. else
  209. {
  210. formatStr = @"yyyyMMddHHmmss'GMT'zzz";
  211. }
  212. }
  213. else
  214. {
  215. if (HasFractionalSeconds)
  216. {
  217. int fCount = d.Length - 1 - d.IndexOf('.');
  218. formatStr = @"yyyyMMddHHmmss." + FString(fCount);
  219. }
  220. else
  221. {
  222. formatStr = @"yyyyMMddHHmmss";
  223. }
  224. // TODO?
  225. // dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID()));
  226. }
  227. return ParseDateString(d, formatStr, makeUniversal);
  228. }
  229. private string FString(
  230. int count)
  231. {
  232. StringBuilder sb = new StringBuilder();
  233. for (int i = 0; i < count; ++i)
  234. {
  235. sb.Append('f');
  236. }
  237. return sb.ToString();
  238. }
  239. private DateTime ParseDateString(string s, string format, bool makeUniversal)
  240. {
  241. /*
  242. * NOTE: DateTime.Kind and DateTimeStyles.AssumeUniversal not available in .NET 1.1
  243. */
  244. DateTimeStyles style = DateTimeStyles.None;
  245. if (Org.BouncyCastle.Utilities.Platform.EndsWith(format, "Z"))
  246. {
  247. try
  248. {
  249. style = (DateTimeStyles)Enums.GetEnumValue(typeof(DateTimeStyles), "AssumeUniversal");
  250. }
  251. catch (Exception)
  252. {
  253. }
  254. style |= DateTimeStyles.AdjustToUniversal;
  255. }
  256. DateTime dt = DateTime.ParseExact(s, format, DateTimeFormatInfo.InvariantInfo, style);
  257. return makeUniversal ? dt.ToUniversalTime() : dt;
  258. }
  259. private bool HasFractionalSeconds
  260. {
  261. get { return time.IndexOf('.') == 14; }
  262. }
  263. private byte[] GetOctets()
  264. {
  265. return Strings.ToAsciiByteArray(time);
  266. }
  267. internal override void Encode(
  268. DerOutputStream derOut)
  269. {
  270. derOut.WriteEncoded(Asn1Tags.GeneralizedTime, GetOctets());
  271. }
  272. protected override bool Asn1Equals(
  273. Asn1Object asn1Object)
  274. {
  275. DerGeneralizedTime other = asn1Object as DerGeneralizedTime;
  276. if (other == null)
  277. return false;
  278. return this.time.Equals(other.time);
  279. }
  280. protected override int Asn1GetHashCode()
  281. {
  282. return time.GetHashCode();
  283. }
  284. }
  285. }
  286. #endif