555 lines
14 KiB
C#
555 lines
14 KiB
C#
using GostCryptography.Properties;
|
|
using System;
|
|
using System.Text;
|
|
|
|
namespace GostCryptography.Asn1.Ber
|
|
{
|
|
[Serializable]
|
|
public abstract class Asn1Time : Asn18BitCharString, IComparable
|
|
{
|
|
public const int January = 1;
|
|
public const int February = 2;
|
|
public const int March = 3;
|
|
public const int April = 4;
|
|
public const int May = 5;
|
|
public const int June = 6;
|
|
public const int July = 7;
|
|
public const int August = 8;
|
|
public const int September = 9;
|
|
public const int October = 10;
|
|
public const int November = 11;
|
|
public const int December = 12;
|
|
|
|
public static readonly short[] DaysInMonth = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
|
|
|
public Asn1Time(short typeCode, bool useDerRules)
|
|
: base(typeCode)
|
|
{
|
|
DerRules = useDerRules;
|
|
Init();
|
|
}
|
|
|
|
public Asn1Time(string data, short typeCode, bool useDerRules)
|
|
: base(data, typeCode)
|
|
{
|
|
DerRules = useDerRules;
|
|
Init();
|
|
}
|
|
|
|
[NonSerialized]
|
|
protected bool Parsed;
|
|
|
|
[NonSerialized]
|
|
protected bool DerRules;
|
|
|
|
[NonSerialized]
|
|
protected int DiffHourValue;
|
|
|
|
public virtual int DiffHour
|
|
{
|
|
get
|
|
{
|
|
if (!Parsed)
|
|
{
|
|
ParseString(Value);
|
|
}
|
|
return DiffHourValue;
|
|
}
|
|
set
|
|
{
|
|
if ((value < -12) || (value > 12))
|
|
{
|
|
throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidDiffHourValue, value);
|
|
}
|
|
|
|
SafeParseString();
|
|
DiffHourValue = value;
|
|
CompileString();
|
|
}
|
|
}
|
|
|
|
[NonSerialized]
|
|
protected int DiffMinValue;
|
|
|
|
public virtual int DiffMinute
|
|
{
|
|
get
|
|
{
|
|
if (!Parsed)
|
|
{
|
|
ParseString(Value);
|
|
}
|
|
|
|
return DiffMinValue;
|
|
}
|
|
}
|
|
|
|
[NonSerialized]
|
|
protected string SecFraction;
|
|
|
|
public virtual string Fraction
|
|
{
|
|
get
|
|
{
|
|
if (!Parsed)
|
|
{
|
|
ParseString(Value);
|
|
}
|
|
return SecFraction;
|
|
}
|
|
set
|
|
{
|
|
SafeParseString();
|
|
SecFraction = value;
|
|
CompileString();
|
|
}
|
|
}
|
|
|
|
[NonSerialized]
|
|
protected int YearValue;
|
|
|
|
public virtual int Year
|
|
{
|
|
get
|
|
{
|
|
if (!Parsed)
|
|
{
|
|
ParseString(Value);
|
|
}
|
|
return YearValue;
|
|
}
|
|
set
|
|
{
|
|
if (value < 0)
|
|
{
|
|
throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidYearValue, value);
|
|
}
|
|
|
|
if (!CheckDate(DayValue, MonthValue, value))
|
|
{
|
|
throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidYearValueForDayAndMonth, value, DayValue, MonthValue);
|
|
}
|
|
|
|
SafeParseString();
|
|
YearValue = value;
|
|
CompileString();
|
|
}
|
|
}
|
|
|
|
[NonSerialized]
|
|
protected int MonthValue;
|
|
|
|
public virtual int Month
|
|
{
|
|
get
|
|
{
|
|
if (!Parsed)
|
|
{
|
|
ParseString(Value);
|
|
}
|
|
|
|
return MonthValue;
|
|
}
|
|
set
|
|
{
|
|
if ((value < 1) || (value > 12))
|
|
{
|
|
throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidMonthValue, value);
|
|
}
|
|
|
|
if (!CheckDate(DayValue, value, YearValue))
|
|
{
|
|
throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidMonthValueForDayAndYear, value, DayValue, YearValue);
|
|
}
|
|
|
|
SafeParseString();
|
|
MonthValue = value;
|
|
CompileString();
|
|
}
|
|
}
|
|
|
|
[NonSerialized]
|
|
protected int DayValue;
|
|
|
|
public virtual int Day
|
|
{
|
|
get
|
|
{
|
|
if (!Parsed)
|
|
{
|
|
ParseString(Value);
|
|
}
|
|
return DayValue;
|
|
}
|
|
set
|
|
{
|
|
if (((value < 1) || (value > 31)) || !CheckDate(value, MonthValue, YearValue))
|
|
{
|
|
throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidDayValueForMonthAndYear, value, MonthValue, YearValue);
|
|
}
|
|
|
|
SafeParseString();
|
|
DayValue = value;
|
|
CompileString();
|
|
}
|
|
}
|
|
|
|
[NonSerialized]
|
|
protected int HourValue;
|
|
|
|
public virtual int Hour
|
|
{
|
|
get
|
|
{
|
|
if (!Parsed)
|
|
{
|
|
ParseString(Value);
|
|
}
|
|
return HourValue;
|
|
}
|
|
set
|
|
{
|
|
if ((value < 0) || (value > 23))
|
|
{
|
|
throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidHourValue, value);
|
|
}
|
|
|
|
SafeParseString();
|
|
HourValue = value;
|
|
CompileString();
|
|
}
|
|
}
|
|
|
|
[NonSerialized]
|
|
protected int MinuteValue;
|
|
|
|
public virtual int Minute
|
|
{
|
|
get
|
|
{
|
|
if (!Parsed)
|
|
{
|
|
ParseString(Value);
|
|
}
|
|
return MinuteValue;
|
|
}
|
|
set
|
|
{
|
|
if ((value < 0) || (value > 59))
|
|
{
|
|
throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidMinuteValue, value);
|
|
}
|
|
|
|
SafeParseString();
|
|
MinuteValue = value;
|
|
CompileString();
|
|
}
|
|
}
|
|
|
|
[NonSerialized]
|
|
protected int SecondValue;
|
|
|
|
public virtual int Second
|
|
{
|
|
get
|
|
{
|
|
if (!Parsed)
|
|
{
|
|
ParseString(Value);
|
|
}
|
|
return SecondValue;
|
|
}
|
|
set
|
|
{
|
|
if ((value < 0) || (value > 59))
|
|
{
|
|
throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidSecondValue, value);
|
|
}
|
|
|
|
SafeParseString();
|
|
SecondValue = value;
|
|
CompileString();
|
|
}
|
|
}
|
|
|
|
[NonSerialized]
|
|
protected bool UtcFlag;
|
|
|
|
public virtual bool Utc
|
|
{
|
|
get
|
|
{
|
|
if (!Parsed)
|
|
{
|
|
ParseString(Value);
|
|
}
|
|
|
|
return UtcFlag;
|
|
}
|
|
set
|
|
{
|
|
if (!DerRules)
|
|
{
|
|
SafeParseString();
|
|
UtcFlag = value;
|
|
CompileString();
|
|
}
|
|
}
|
|
}
|
|
|
|
public virtual int CompareTo(object other)
|
|
{
|
|
if (other is DateTime)
|
|
{
|
|
var time2 = (DateTime)other;
|
|
return (int)(GetTime().Ticks - time2.Ticks);
|
|
}
|
|
return (int)(GetTime().Ticks - ((Asn1Time)other).GetTime().Ticks);
|
|
}
|
|
|
|
protected static char CharAt(string s, int index)
|
|
{
|
|
if (index >= s.Length)
|
|
{
|
|
return '\0';
|
|
}
|
|
|
|
return s[index];
|
|
}
|
|
|
|
private static bool CheckDate(int day, int month, int year)
|
|
{
|
|
if ((day <= 0) || (month <= 0))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if ((year >= 0) && (month > 0))
|
|
{
|
|
int num = DaysInMonth[month];
|
|
|
|
if (((month == 2) && ((year % 4) == 0)) && (((year % 100) != 0) || ((year % 400) == 0)))
|
|
{
|
|
num++;
|
|
}
|
|
|
|
if ((day >= 1) && (day <= num))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
else if (month > 0)
|
|
{
|
|
if (day <= DaysInMonth[month])
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if ((month == 2) && (day <= (DaysInMonth[month] + 1)))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public virtual void Clear()
|
|
{
|
|
YearValue = MonthValue = DayValue = HourValue = -1;
|
|
MinuteValue = SecondValue = DiffHourValue = DiffMinValue = 0;
|
|
UtcFlag = DerRules;
|
|
Parsed = true;
|
|
SecFraction = "";
|
|
Value = "";
|
|
}
|
|
|
|
protected abstract bool CompileString();
|
|
|
|
protected override void Decode(Asn1BerDecodeBuffer buffer, bool explicitTagging, int implicitLength, Asn1Tag tag)
|
|
{
|
|
Parsed = false;
|
|
base.Decode(buffer, explicitTagging, implicitLength, tag);
|
|
DerRules = buffer is Asn1DerDecodeBuffer;
|
|
}
|
|
|
|
protected override int Encode(Asn1BerEncodeBuffer buffer, bool explicitTagging, Asn1Tag tag)
|
|
{
|
|
SafeParseString();
|
|
|
|
var flag = buffer is Asn1DerEncodeBuffer;
|
|
|
|
if (DerRules != flag)
|
|
{
|
|
DerRules = flag;
|
|
|
|
if (!CompileString())
|
|
{
|
|
throw ExceptionUtility.CryptographicException(Resources.Asn1TimeStringCouldNotBeGenerated);
|
|
}
|
|
}
|
|
|
|
return base.Encode(buffer, explicitTagging, tag);
|
|
}
|
|
|
|
public virtual void Encode(Asn1BerOutputStream outs, bool explicitTagging, Asn1Tag tag)
|
|
{
|
|
SafeParseString();
|
|
outs.EncodeCharString(Value, explicitTagging, tag);
|
|
}
|
|
|
|
public override bool Equals(object value)
|
|
{
|
|
if (value is Asn1Time)
|
|
{
|
|
return GetTime().Equals(((Asn1Time)value).GetTime());
|
|
}
|
|
|
|
return ((value is DateTime) && GetTime().Equals((DateTime)value));
|
|
}
|
|
|
|
public virtual int GetDiff()
|
|
{
|
|
if (!Parsed)
|
|
{
|
|
ParseString(Value);
|
|
}
|
|
|
|
return ((DiffHourValue * 60) + DiffMinValue);
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return Value.GetHashCode();
|
|
}
|
|
|
|
public virtual DateTime GetTime()
|
|
{
|
|
if (!string.IsNullOrEmpty(SecFraction))
|
|
{
|
|
return new DateTime(YearValue, MonthValue, DayValue, HourValue, MinuteValue, SecondValue, int.Parse(SecFraction));
|
|
}
|
|
|
|
return new DateTime(YearValue, MonthValue, DayValue, HourValue, MinuteValue, SecondValue);
|
|
}
|
|
|
|
protected virtual void Init()
|
|
{
|
|
YearValue = MonthValue = DayValue = HourValue = -1;
|
|
MinuteValue = SecondValue = 0;
|
|
DiffHourValue = DiffMinValue = 0;
|
|
UtcFlag = DerRules;
|
|
SecFraction = "";
|
|
}
|
|
|
|
protected static int ParseInt(string str, IntHolder off, int len)
|
|
{
|
|
if ((off.Value + len) > str.Length)
|
|
{
|
|
throw ExceptionUtility.ArgumentOutOfRange("off");
|
|
}
|
|
|
|
var mValue = off.Value;
|
|
off.Value += len;
|
|
|
|
return int.Parse(str.Substring(mValue, len));
|
|
}
|
|
|
|
public abstract void ParseString(string data);
|
|
|
|
protected virtual void PutInteger(int width, int value)
|
|
{
|
|
PutInteger(StringBuffer, width, value);
|
|
}
|
|
|
|
public static void PutInteger(StringBuilder data, int width, int value)
|
|
{
|
|
var str = Convert.ToString(value);
|
|
var length = str.Length;
|
|
|
|
if (length < width)
|
|
{
|
|
for (var i = length; i < width; i++)
|
|
{
|
|
data.Append('0');
|
|
}
|
|
}
|
|
else if (length > width)
|
|
{
|
|
str = str.Substring(length - width);
|
|
}
|
|
|
|
data.Append(str);
|
|
}
|
|
|
|
protected virtual void SafeParseString()
|
|
{
|
|
try
|
|
{
|
|
if (!Parsed)
|
|
{
|
|
ParseString(Value);
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
}
|
|
|
|
public virtual void SetDiff(int inMinutes)
|
|
{
|
|
if (Math.Abs(inMinutes) > 720)
|
|
{
|
|
throw ExceptionUtility.CryptographicException(Resources.InvalidDiffValue, inMinutes);
|
|
}
|
|
|
|
SafeParseString();
|
|
DiffHourValue = inMinutes / 60;
|
|
DiffMinValue = inMinutes % 60;
|
|
CompileString();
|
|
}
|
|
|
|
public virtual void SetDiff(int dhour, int dminute)
|
|
{
|
|
if ((dhour < -12) || (dhour > 12))
|
|
{
|
|
throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidDiffHourValue, dhour);
|
|
}
|
|
|
|
if (Math.Abs(dminute) > 59)
|
|
{
|
|
throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidDiffMinuteValue, dminute);
|
|
}
|
|
|
|
SafeParseString();
|
|
DiffHourValue = dhour;
|
|
|
|
if (dhour < 0)
|
|
{
|
|
DiffMinValue = -Math.Abs(dminute);
|
|
}
|
|
else
|
|
{
|
|
DiffMinValue = Math.Abs(dminute);
|
|
}
|
|
|
|
CompileString();
|
|
}
|
|
|
|
public virtual void SetTime(DateTime time)
|
|
{
|
|
Clear();
|
|
YearValue = time.Year;
|
|
MonthValue = time.Month;
|
|
DayValue = time.Day;
|
|
HourValue = time.Hour;
|
|
MinuteValue = time.Minute;
|
|
SecondValue = time.Second;
|
|
SecFraction = Convert.ToString(time.Millisecond);
|
|
DiffHourValue = DiffMinValue = 0;
|
|
UtcFlag = DerRules;
|
|
CompileString();
|
|
}
|
|
}
|
|
}
|