DerUTCTime.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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. * UTC time object.
  10. */
  11. public class DerUtcTime
  12. : Asn1Object
  13. {
  14. private readonly string time;
  15. /**
  16. * return an UTC Time from the passed in object.
  17. *
  18. * @exception ArgumentException if the object cannot be converted.
  19. */
  20. public static DerUtcTime GetInstance(
  21. object obj)
  22. {
  23. if (obj == null || obj is DerUtcTime)
  24. {
  25. return (DerUtcTime)obj;
  26. }
  27. throw new ArgumentException("illegal object in GetInstance: " + Org.BouncyCastle.Utilities.Platform.GetTypeName(obj));
  28. }
  29. /**
  30. * return an UTC Time 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 DerUtcTime GetInstance(
  39. Asn1TaggedObject obj,
  40. bool isExplicit)
  41. {
  42. Asn1Object o = obj.GetObject();
  43. if (isExplicit || o is DerUtcTime)
  44. {
  45. return GetInstance(o);
  46. }
  47. return new DerUtcTime(((Asn1OctetString)o).GetOctets());
  48. }
  49. /**
  50. * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
  51. * never encoded. When you're creating one of these objects from scratch, that's
  52. * what you want to use, otherwise we'll try to deal with whatever Gets read from
  53. * the input stream... (this is why the input format is different from the GetTime()
  54. * method output).
  55. * <p>
  56. * @param time the time string.</p>
  57. */
  58. public DerUtcTime(
  59. string time)
  60. {
  61. if (time == null)
  62. throw new ArgumentNullException("time");
  63. this.time = time;
  64. try
  65. {
  66. ToDateTime();
  67. }
  68. catch (FormatException e)
  69. {
  70. throw new ArgumentException("invalid date string: " + e.Message);
  71. }
  72. }
  73. /**
  74. * base constructor from a DateTime object
  75. */
  76. public DerUtcTime(
  77. DateTime time)
  78. {
  79. #if PORTABLE || NETFX_CORE
  80. this.time = time.ToUniversalTime().ToString("yyMMddHHmmss", CultureInfo.InvariantCulture) + "Z";
  81. #else
  82. this.time = time.ToString("yyMMddHHmmss", CultureInfo.InvariantCulture) + "Z";
  83. #endif
  84. }
  85. internal DerUtcTime(
  86. byte[] bytes)
  87. {
  88. //
  89. // explicitly convert to characters
  90. //
  91. this.time = Strings.FromAsciiByteArray(bytes);
  92. }
  93. // public DateTime ToDateTime()
  94. // {
  95. // string tm = this.AdjustedTimeString;
  96. //
  97. // return new DateTime(
  98. // Int16.Parse(tm.Substring(0, 4)),
  99. // Int16.Parse(tm.Substring(4, 2)),
  100. // Int16.Parse(tm.Substring(6, 2)),
  101. // Int16.Parse(tm.Substring(8, 2)),
  102. // Int16.Parse(tm.Substring(10, 2)),
  103. // Int16.Parse(tm.Substring(12, 2)));
  104. // }
  105. /**
  106. * return the time as a date based on whatever a 2 digit year will return. For
  107. * standardised processing use ToAdjustedDateTime().
  108. *
  109. * @return the resulting date
  110. * @exception ParseException if the date string cannot be parsed.
  111. */
  112. public DateTime ToDateTime()
  113. {
  114. return ParseDateString(TimeString, @"yyMMddHHmmss'GMT'zzz");
  115. }
  116. /**
  117. * return the time as an adjusted date
  118. * in the range of 1950 - 2049.
  119. *
  120. * @return a date in the range of 1950 to 2049.
  121. * @exception ParseException if the date string cannot be parsed.
  122. */
  123. public DateTime ToAdjustedDateTime()
  124. {
  125. return ParseDateString(AdjustedTimeString, @"yyyyMMddHHmmss'GMT'zzz");
  126. }
  127. private DateTime ParseDateString(
  128. string dateStr,
  129. string formatStr)
  130. {
  131. DateTime dt = DateTime.ParseExact(
  132. dateStr,
  133. formatStr,
  134. DateTimeFormatInfo.InvariantInfo);
  135. return dt.ToUniversalTime();
  136. }
  137. /**
  138. * return the time - always in the form of
  139. * YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
  140. * <p>
  141. * Normally in a certificate we would expect "Z" rather than "GMT",
  142. * however adding the "GMT" means we can just use:
  143. * <pre>
  144. * dateF = new SimpleDateFormat("yyMMddHHmmssz");
  145. * </pre>
  146. * To read in the time and Get a date which is compatible with our local
  147. * time zone.</p>
  148. * <p>
  149. * <b>Note:</b> In some cases, due to the local date processing, this
  150. * may lead to unexpected results. If you want to stick the normal
  151. * convention of 1950 to 2049 use the GetAdjustedTime() method.</p>
  152. */
  153. public string TimeString
  154. {
  155. get
  156. {
  157. //
  158. // standardise the format.
  159. //
  160. if (time.IndexOf('-') < 0 && time.IndexOf('+') < 0)
  161. {
  162. if (time.Length == 11)
  163. {
  164. return time.Substring(0, 10) + "00GMT+00:00";
  165. }
  166. else
  167. {
  168. return time.Substring(0, 12) + "GMT+00:00";
  169. }
  170. }
  171. else
  172. {
  173. int index = time.IndexOf('-');
  174. if (index < 0)
  175. {
  176. index = time.IndexOf('+');
  177. }
  178. string d = time;
  179. if (index == time.Length - 3)
  180. {
  181. d += "00";
  182. }
  183. if (index == 10)
  184. {
  185. return d.Substring(0, 10) + "00GMT" + d.Substring(10, 3) + ":" + d.Substring(13, 2);
  186. }
  187. else
  188. {
  189. return d.Substring(0, 12) + "GMT" + d.Substring(12, 3) + ":" + d.Substring(15, 2);
  190. }
  191. }
  192. }
  193. }
  194. [Obsolete("Use 'AdjustedTimeString' property instead")]
  195. public string AdjustedTime
  196. {
  197. get { return AdjustedTimeString; }
  198. }
  199. /// <summary>
  200. /// Return a time string as an adjusted date with a 4 digit year.
  201. /// This goes in the range of 1950 - 2049.
  202. /// </summary>
  203. public string AdjustedTimeString
  204. {
  205. get
  206. {
  207. string d = TimeString;
  208. string c = d[0] < '5' ? "20" : "19";
  209. return c + d;
  210. }
  211. }
  212. private byte[] GetOctets()
  213. {
  214. return Strings.ToAsciiByteArray(time);
  215. }
  216. internal override void Encode(
  217. DerOutputStream derOut)
  218. {
  219. derOut.WriteEncoded(Asn1Tags.UtcTime, GetOctets());
  220. }
  221. protected override bool Asn1Equals(
  222. Asn1Object asn1Object)
  223. {
  224. DerUtcTime other = asn1Object as DerUtcTime;
  225. if (other == null)
  226. return false;
  227. return this.time.Equals(other.time);
  228. }
  229. protected override int Asn1GetHashCode()
  230. {
  231. return time.GetHashCode();
  232. }
  233. public override string ToString()
  234. {
  235. return time;
  236. }
  237. }
  238. }
  239. #endif