123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
- #pragma warning disable
- using System;
- using System.Globalization;
- using System.IO;
- using System.Text;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
- namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Asn1
- {
- /// <summary>GeneralizedTime ASN.1 type</summary>
- public class Asn1GeneralizedTime
- : Asn1Object
- {
- internal class Meta : Asn1UniversalType
- {
- internal static readonly Asn1UniversalType Instance = new Meta();
- private Meta() : base(typeof(Asn1GeneralizedTime), Asn1Tags.GeneralizedTime) { }
- internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
- {
- return CreatePrimitive(octetString.GetOctets());
- }
- }
- public static Asn1GeneralizedTime GetInstance(object obj)
- {
- if (obj == null)
- return null;
- if (obj is Asn1GeneralizedTime asn1GeneralizedTime)
- return asn1GeneralizedTime;
- if (obj is IAsn1Convertible asn1Convertible)
- {
- Asn1Object asn1Object = asn1Convertible.ToAsn1Object();
- if (asn1Object is Asn1GeneralizedTime converted)
- return converted;
- }
- else if (obj is byte[] bytes)
- {
- try
- {
- return (Asn1GeneralizedTime)Meta.Instance.FromByteArray(bytes);
- }
- catch (IOException e)
- {
- throw new ArgumentException("failed to construct generalized time from byte[]: " + e.Message);
- }
- }
- throw new ArgumentException("illegal object in GetInstance: " + Org.BouncyCastle.Utilities.Platform.GetTypeName(obj), nameof(obj));
- }
- public static Asn1GeneralizedTime GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
- {
- return (Asn1GeneralizedTime)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
- }
- private readonly string m_timeString;
- private readonly bool m_timeStringCanonical;
- private readonly DateTime m_dateTime;
- public Asn1GeneralizedTime(string timeString)
- {
- m_timeString = timeString ?? throw new ArgumentNullException(nameof(timeString));
- m_timeStringCanonical = false; // TODO Dynamic check?
- try
- {
- m_dateTime = FromString(timeString);
- }
- catch (FormatException e)
- {
- throw new ArgumentException("invalid date string: " + e.Message);
- }
- }
- public Asn1GeneralizedTime(DateTime dateTime)
- {
- dateTime = dateTime.ToUniversalTime();
- m_dateTime = dateTime;
- m_timeString = ToStringCanonical(dateTime);
- m_timeStringCanonical = true;
- }
- // TODO TimeZoneInfo or other locale-specific constructors?
- internal Asn1GeneralizedTime(byte[] contents)
- : this(Encoding.ASCII.GetString(contents))
- {
- }
- public string TimeString => m_timeString;
- public DateTime ToDateTime()
- {
- return m_dateTime;
- }
- internal byte[] GetContents(int encoding)
- {
- if (encoding == Asn1OutputStream.EncodingDer && !m_timeStringCanonical)
- return Encoding.ASCII.GetBytes(ToStringCanonical(m_dateTime));
- return Encoding.ASCII.GetBytes(m_timeString);
- }
- internal override IAsn1Encoding GetEncoding(int encoding)
- {
- return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.GeneralizedTime, GetContents(encoding));
- }
- internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo)
- {
- return new PrimitiveEncoding(tagClass, tagNo, GetContents(encoding));
- }
- protected override bool Asn1Equals(Asn1Object asn1Object)
- {
- if (!(asn1Object is Asn1GeneralizedTime that))
- return false;
- // TODO Performance
- return Arrays.AreEqual(
- this.GetContents(Asn1OutputStream.EncodingDer),
- that.GetContents(Asn1OutputStream.EncodingDer));
- }
- protected override int Asn1GetHashCode()
- {
- // TODO Performance
- return Arrays.GetHashCode(
- this.GetContents(Asn1OutputStream.EncodingDer));
- }
- internal static Asn1GeneralizedTime CreatePrimitive(byte[] contents)
- {
- return new Asn1GeneralizedTime(contents);
- }
- private static DateTime FromString(string s)
- {
- if (s.Length < 10)
- throw new FormatException();
- s = s.Replace(',', '.');
- if (Org.BouncyCastle.Utilities.Platform.EndsWith(s, "Z"))
- {
- switch (s.Length)
- {
- case 11: return ParseUtc(s, @"yyyyMMddHH\Z");
- case 13: return ParseUtc(s, @"yyyyMMddHHmm\Z");
- case 15: return ParseUtc(s, @"yyyyMMddHHmmss\Z");
- case 17: return ParseUtc(s, @"yyyyMMddHHmmss.f\Z");
- case 18: return ParseUtc(s, @"yyyyMMddHHmmss.ff\Z");
- case 19: return ParseUtc(s, @"yyyyMMddHHmmss.fff\Z");
- case 20: return ParseUtc(s, @"yyyyMMddHHmmss.ffff\Z");
- case 21: return ParseUtc(s, @"yyyyMMddHHmmss.fffff\Z");
- case 22: return ParseUtc(s, @"yyyyMMddHHmmss.ffffff\Z");
- case 23: return ParseUtc(s, @"yyyyMMddHHmmss.fffffff\Z");
- default:
- throw new FormatException();
- }
- }
- int signIndex = IndexOfSign(s, System.Math.Max(10, s.Length - 5));
- if (signIndex < 0)
- {
- switch (s.Length)
- {
- case 10: return ParseLocal(s, @"yyyyMMddHH");
- case 12: return ParseLocal(s, @"yyyyMMddHHmm");
- case 14: return ParseLocal(s, @"yyyyMMddHHmmss");
- case 16: return ParseLocal(s, @"yyyyMMddHHmmss.f");
- case 17: return ParseLocal(s, @"yyyyMMddHHmmss.ff");
- case 18: return ParseLocal(s, @"yyyyMMddHHmmss.fff");
- case 19: return ParseLocal(s, @"yyyyMMddHHmmss.ffff");
- case 20: return ParseLocal(s, @"yyyyMMddHHmmss.fffff");
- case 21: return ParseLocal(s, @"yyyyMMddHHmmss.ffffff");
- case 22: return ParseLocal(s, @"yyyyMMddHHmmss.fffffff");
- default:
- throw new FormatException();
- }
- }
- if (signIndex == s.Length - 5)
- {
- switch (s.Length)
- {
- case 15: return ParseTimeZone(s, @"yyyyMMddHHzzz");
- case 17: return ParseTimeZone(s, @"yyyyMMddHHmmzzz");
- case 19: return ParseTimeZone(s, @"yyyyMMddHHmmsszzz");
- case 21: return ParseTimeZone(s, @"yyyyMMddHHmmss.fzzz");
- case 22: return ParseTimeZone(s, @"yyyyMMddHHmmss.ffzzz");
- case 23: return ParseTimeZone(s, @"yyyyMMddHHmmss.fffzzz");
- case 24: return ParseTimeZone(s, @"yyyyMMddHHmmss.ffffzzz");
- case 25: return ParseTimeZone(s, @"yyyyMMddHHmmss.fffffzzz");
- case 26: return ParseTimeZone(s, @"yyyyMMddHHmmss.ffffffzzz");
- case 27: return ParseTimeZone(s, @"yyyyMMddHHmmss.fffffffzzz");
- default:
- throw new FormatException();
- }
- }
- if (signIndex == s.Length - 3)
- {
- switch (s.Length)
- {
- case 13: return ParseTimeZone(s, @"yyyyMMddHHzz");
- case 15: return ParseTimeZone(s, @"yyyyMMddHHmmzz");
- case 17: return ParseTimeZone(s, @"yyyyMMddHHmmsszz");
- case 19: return ParseTimeZone(s, @"yyyyMMddHHmmss.fzz");
- case 20: return ParseTimeZone(s, @"yyyyMMddHHmmss.ffzz");
- case 21: return ParseTimeZone(s, @"yyyyMMddHHmmss.fffzz");
- case 22: return ParseTimeZone(s, @"yyyyMMddHHmmss.ffffzz");
- case 23: return ParseTimeZone(s, @"yyyyMMddHHmmss.fffffzz");
- case 24: return ParseTimeZone(s, @"yyyyMMddHHmmss.ffffffzz");
- case 25: return ParseTimeZone(s, @"yyyyMMddHHmmss.fffffffzz");
- default:
- throw new FormatException();
- }
- }
- throw new FormatException();
- }
- private static int IndexOfSign(string s, int startIndex)
- {
- int index = Org.BouncyCastle.Utilities.Platform.IndexOf(s, '+', startIndex);
- if (index < 0)
- {
- index = Org.BouncyCastle.Utilities.Platform.IndexOf(s, '-', startIndex);
- }
- return index;
- }
- private static DateTime ParseLocal(string s, string format)
- {
- return DateTime.ParseExact(s, format, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeLocal);
- }
- private static DateTime ParseTimeZone(string s, string format)
- {
- return DateTime.ParseExact(s, format, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AdjustToUniversal);
- }
- private static DateTime ParseUtc(string s, string format)
- {
- return DateTime.ParseExact(s, format, DateTimeFormatInfo.InvariantInfo,
- DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal);
- }
- private static string ToStringCanonical(DateTime dateTime)
- {
- return dateTime.ToUniversalTime().ToString(@"yyyyMMddHHmmss.FFFFFFFK", DateTimeFormatInfo.InvariantInfo);
- }
- }
- }
- #pragma warning restore
- #endif
|