202 lines
4.4 KiB
C#
202 lines
4.4 KiB
C#
using System;
|
|
using System.Globalization;
|
|
using System.Text;
|
|
using Org.BouncyCastle.Utilities;
|
|
|
|
namespace Org.BouncyCastle.Asn1;
|
|
|
|
public class DerGeneralizedTime : Asn1Object
|
|
{
|
|
private readonly string time;
|
|
|
|
public string TimeString => time;
|
|
|
|
private bool HasFractionalSeconds => time.IndexOf('.') == 14;
|
|
|
|
public static DerGeneralizedTime GetInstance(object obj)
|
|
{
|
|
if (obj == null || obj is DerGeneralizedTime)
|
|
{
|
|
return (DerGeneralizedTime)obj;
|
|
}
|
|
throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj");
|
|
}
|
|
|
|
public static DerGeneralizedTime GetInstance(Asn1TaggedObject obj, bool isExplicit)
|
|
{
|
|
Asn1Object asn1Object = obj.GetObject();
|
|
if (isExplicit || asn1Object is DerGeneralizedTime)
|
|
{
|
|
return GetInstance(asn1Object);
|
|
}
|
|
return new DerGeneralizedTime(((Asn1OctetString)asn1Object).GetOctets());
|
|
}
|
|
|
|
public DerGeneralizedTime(string time)
|
|
{
|
|
this.time = time;
|
|
try
|
|
{
|
|
ToDateTime();
|
|
}
|
|
catch (FormatException ex)
|
|
{
|
|
throw new ArgumentException("invalid date string: " + ex.Message);
|
|
}
|
|
}
|
|
|
|
public DerGeneralizedTime(DateTime time)
|
|
{
|
|
this.time = time.ToString("yyyyMMddHHmmss\\Z");
|
|
}
|
|
|
|
internal DerGeneralizedTime(byte[] bytes)
|
|
{
|
|
time = Strings.FromAsciiByteArray(bytes);
|
|
}
|
|
|
|
public string GetTime()
|
|
{
|
|
if (time[time.Length - 1] == 'Z')
|
|
{
|
|
return time.Substring(0, time.Length - 1) + "GMT+00:00";
|
|
}
|
|
int num = time.Length - 5;
|
|
char c = time[num];
|
|
if (c == '-' || c == '+')
|
|
{
|
|
return time.Substring(0, num) + "GMT" + time.Substring(num, 3) + ":" + time.Substring(num + 3);
|
|
}
|
|
num = time.Length - 3;
|
|
c = time[num];
|
|
if (c == '-' || c == '+')
|
|
{
|
|
return time.Substring(0, num) + "GMT" + time.Substring(num) + ":00";
|
|
}
|
|
return time + CalculateGmtOffset();
|
|
}
|
|
|
|
private string CalculateGmtOffset()
|
|
{
|
|
char c = '+';
|
|
DateTime dateTime = ToDateTime();
|
|
TimeSpan timeSpan = TimeZone.CurrentTimeZone.GetUtcOffset(dateTime);
|
|
if (timeSpan.CompareTo((object?)TimeSpan.Zero) < 0)
|
|
{
|
|
c = '-';
|
|
timeSpan = timeSpan.Duration();
|
|
}
|
|
int hours = timeSpan.Hours;
|
|
int minutes = timeSpan.Minutes;
|
|
return "GMT" + c + Convert(hours) + ":" + Convert(minutes);
|
|
}
|
|
|
|
private static string Convert(int time)
|
|
{
|
|
if (time < 10)
|
|
{
|
|
return "0" + time;
|
|
}
|
|
return time.ToString();
|
|
}
|
|
|
|
public DateTime ToDateTime()
|
|
{
|
|
string text = time;
|
|
bool makeUniversal = false;
|
|
string format;
|
|
if (Platform.EndsWith(text, "Z"))
|
|
{
|
|
if (HasFractionalSeconds)
|
|
{
|
|
int count = text.Length - text.IndexOf('.') - 2;
|
|
format = "yyyyMMddHHmmss." + FString(count) + "\\Z";
|
|
}
|
|
else
|
|
{
|
|
format = "yyyyMMddHHmmss\\Z";
|
|
}
|
|
}
|
|
else if (time.IndexOf('-') > 0 || time.IndexOf('+') > 0)
|
|
{
|
|
text = GetTime();
|
|
makeUniversal = true;
|
|
if (HasFractionalSeconds)
|
|
{
|
|
int count2 = Platform.IndexOf(text, "GMT") - 1 - text.IndexOf('.');
|
|
format = "yyyyMMddHHmmss." + FString(count2) + "'GMT'zzz";
|
|
}
|
|
else
|
|
{
|
|
format = "yyyyMMddHHmmss'GMT'zzz";
|
|
}
|
|
}
|
|
else if (HasFractionalSeconds)
|
|
{
|
|
int count3 = text.Length - 1 - text.IndexOf('.');
|
|
format = "yyyyMMddHHmmss." + FString(count3);
|
|
}
|
|
else
|
|
{
|
|
format = "yyyyMMddHHmmss";
|
|
}
|
|
return ParseDateString(text, format, makeUniversal);
|
|
}
|
|
|
|
private string FString(int count)
|
|
{
|
|
StringBuilder stringBuilder = new StringBuilder();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
stringBuilder.Append('f');
|
|
}
|
|
return stringBuilder.ToString();
|
|
}
|
|
|
|
private DateTime ParseDateString(string s, string format, bool makeUniversal)
|
|
{
|
|
DateTimeStyles dateTimeStyles = DateTimeStyles.None;
|
|
if (Platform.EndsWith(format, "Z"))
|
|
{
|
|
try
|
|
{
|
|
dateTimeStyles = (DateTimeStyles)Enums.GetEnumValue(typeof(DateTimeStyles), "AssumeUniversal");
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
dateTimeStyles |= DateTimeStyles.AdjustToUniversal;
|
|
}
|
|
DateTime result = DateTime.ParseExact(s, format, DateTimeFormatInfo.InvariantInfo, dateTimeStyles);
|
|
if (!makeUniversal)
|
|
{
|
|
return result;
|
|
}
|
|
return result.ToUniversalTime();
|
|
}
|
|
|
|
private byte[] GetOctets()
|
|
{
|
|
return Strings.ToAsciiByteArray(time);
|
|
}
|
|
|
|
internal override void Encode(DerOutputStream derOut)
|
|
{
|
|
derOut.WriteEncoded(24, GetOctets());
|
|
}
|
|
|
|
protected override bool Asn1Equals(Asn1Object asn1Object)
|
|
{
|
|
if (!(asn1Object is DerGeneralizedTime derGeneralizedTime))
|
|
{
|
|
return false;
|
|
}
|
|
return time.Equals(derGeneralizedTime.time);
|
|
}
|
|
|
|
protected override int Asn1GetHashCode()
|
|
{
|
|
return time.GetHashCode();
|
|
}
|
|
}
|