You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
276 lines
6.8 KiB
276 lines
6.8 KiB
8 months ago
|
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||
|
#pragma warning disable
|
||
|
using System;
|
||
|
using System.Globalization;
|
||
|
using System.Text;
|
||
|
|
||
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||
|
|
||
|
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1
|
||
|
{
|
||
|
/**
|
||
|
* UTC time object.
|
||
|
*/
|
||
|
public class DerUtcTime
|
||
|
: Asn1Object
|
||
|
{
|
||
|
private readonly string time;
|
||
|
|
||
|
/**
|
||
|
* return an UTC Time from the passed in object.
|
||
|
*
|
||
|
* @exception ArgumentException if the object cannot be converted.
|
||
|
*/
|
||
|
public static DerUtcTime GetInstance(
|
||
|
object obj)
|
||
|
{
|
||
|
if (obj == null || obj is DerUtcTime)
|
||
|
{
|
||
|
return (DerUtcTime)obj;
|
||
|
}
|
||
|
|
||
|
throw new ArgumentException("illegal object in GetInstance: " + BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.GetTypeName(obj));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* return an UTC Time from a tagged object.
|
||
|
*
|
||
|
* @param obj the tagged object holding the object we want
|
||
|
* @param explicitly true if the object is meant to be explicitly
|
||
|
* tagged false otherwise.
|
||
|
* @exception ArgumentException if the tagged object cannot
|
||
|
* be converted.
|
||
|
*/
|
||
|
public static DerUtcTime GetInstance(
|
||
|
Asn1TaggedObject obj,
|
||
|
bool isExplicit)
|
||
|
{
|
||
|
Asn1Object o = obj.GetObject();
|
||
|
|
||
|
if (isExplicit || o is DerUtcTime)
|
||
|
{
|
||
|
return GetInstance(o);
|
||
|
}
|
||
|
|
||
|
return new DerUtcTime(((Asn1OctetString)o).GetOctets());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
|
||
|
* never encoded. When you're creating one of these objects from scratch, that's
|
||
|
* what you want to use, otherwise we'll try to deal with whatever Gets read from
|
||
|
* the input stream... (this is why the input format is different from the GetTime()
|
||
|
* method output).
|
||
|
* <p>
|
||
|
* @param time the time string.</p>
|
||
|
*/
|
||
|
public DerUtcTime(
|
||
|
string time)
|
||
|
{
|
||
|
if (time == null)
|
||
|
throw new ArgumentNullException("time");
|
||
|
|
||
|
this.time = time;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
ToDateTime();
|
||
|
}
|
||
|
catch (FormatException e)
|
||
|
{
|
||
|
throw new ArgumentException("invalid date string: " + e.Message);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* base constructor from a DateTime object
|
||
|
*/
|
||
|
public DerUtcTime(
|
||
|
DateTime time)
|
||
|
{
|
||
|
#if PORTABLE || NETFX_CORE
|
||
|
this.time = time.ToUniversalTime().ToString("yyMMddHHmmss", CultureInfo.InvariantCulture) + "Z";
|
||
|
#else
|
||
|
this.time = time.ToString("yyMMddHHmmss", CultureInfo.InvariantCulture) + "Z";
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
internal DerUtcTime(
|
||
|
byte[] bytes)
|
||
|
{
|
||
|
//
|
||
|
// explicitly convert to characters
|
||
|
//
|
||
|
this.time = Strings.FromAsciiByteArray(bytes);
|
||
|
}
|
||
|
|
||
|
// public DateTime ToDateTime()
|
||
|
// {
|
||
|
// string tm = this.AdjustedTimeString;
|
||
|
//
|
||
|
// return new DateTime(
|
||
|
// Int16.Parse(tm.Substring(0, 4)),
|
||
|
// Int16.Parse(tm.Substring(4, 2)),
|
||
|
// Int16.Parse(tm.Substring(6, 2)),
|
||
|
// Int16.Parse(tm.Substring(8, 2)),
|
||
|
// Int16.Parse(tm.Substring(10, 2)),
|
||
|
// Int16.Parse(tm.Substring(12, 2)));
|
||
|
// }
|
||
|
|
||
|
/**
|
||
|
* return the time as a date based on whatever a 2 digit year will return. For
|
||
|
* standardised processing use ToAdjustedDateTime().
|
||
|
*
|
||
|
* @return the resulting date
|
||
|
* @exception ParseException if the date string cannot be parsed.
|
||
|
*/
|
||
|
public DateTime ToDateTime()
|
||
|
{
|
||
|
return ParseDateString(TimeString, @"yyMMddHHmmss'GMT'zzz");
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* return the time as an adjusted date
|
||
|
* in the range of 1950 - 2049.
|
||
|
*
|
||
|
* @return a date in the range of 1950 to 2049.
|
||
|
* @exception ParseException if the date string cannot be parsed.
|
||
|
*/
|
||
|
public DateTime ToAdjustedDateTime()
|
||
|
{
|
||
|
return ParseDateString(AdjustedTimeString, @"yyyyMMddHHmmss'GMT'zzz");
|
||
|
}
|
||
|
|
||
|
private DateTime ParseDateString(
|
||
|
string dateStr,
|
||
|
string formatStr)
|
||
|
{
|
||
|
DateTime dt = DateTime.ParseExact(
|
||
|
dateStr,
|
||
|
formatStr,
|
||
|
DateTimeFormatInfo.InvariantInfo);
|
||
|
|
||
|
return dt.ToUniversalTime();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* return the time - always in the form of
|
||
|
* YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
|
||
|
* <p>
|
||
|
* Normally in a certificate we would expect "Z" rather than "GMT",
|
||
|
* however adding the "GMT" means we can just use:
|
||
|
* <pre>
|
||
|
* dateF = new SimpleDateFormat("yyMMddHHmmssz");
|
||
|
* </pre>
|
||
|
* To read in the time and Get a date which is compatible with our local
|
||
|
* time zone.</p>
|
||
|
* <p>
|
||
|
* <b>Note:</b> In some cases, due to the local date processing, this
|
||
|
* may lead to unexpected results. If you want to stick the normal
|
||
|
* convention of 1950 to 2049 use the GetAdjustedTime() method.</p>
|
||
|
*/
|
||
|
public string TimeString
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
//
|
||
|
// standardise the format.
|
||
|
//
|
||
|
if (time.IndexOf('-') < 0 && time.IndexOf('+') < 0)
|
||
|
{
|
||
|
if (time.Length == 11)
|
||
|
{
|
||
|
return time.Substring(0, 10) + "00GMT+00:00";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return time.Substring(0, 12) + "GMT+00:00";
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int index = time.IndexOf('-');
|
||
|
if (index < 0)
|
||
|
{
|
||
|
index = time.IndexOf('+');
|
||
|
}
|
||
|
string d = time;
|
||
|
|
||
|
if (index == time.Length - 3)
|
||
|
{
|
||
|
d += "00";
|
||
|
}
|
||
|
|
||
|
if (index == 10)
|
||
|
{
|
||
|
return d.Substring(0, 10) + "00GMT" + d.Substring(10, 3) + ":" + d.Substring(13, 2);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return d.Substring(0, 12) + "GMT" + d.Substring(12, 3) + ":" + d.Substring(15, 2);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
public string AdjustedTime
|
||
|
{
|
||
|
get { return AdjustedTimeString; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Return a time string as an adjusted date with a 4 digit year.
|
||
|
/// This goes in the range of 1950 - 2049.
|
||
|
/// </summary>
|
||
|
public string AdjustedTimeString
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
string d = TimeString;
|
||
|
string c = d[0] < '5' ? "20" : "19";
|
||
|
|
||
|
return c + d;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private byte[] GetOctets()
|
||
|
{
|
||
|
return Strings.ToAsciiByteArray(time);
|
||
|
}
|
||
|
|
||
|
internal override int EncodedLength(bool withID)
|
||
|
{
|
||
|
return Asn1OutputStream.GetLengthOfEncodingDL(withID, time.Length);
|
||
|
}
|
||
|
|
||
|
internal override void Encode(Asn1OutputStream asn1Out, bool withID)
|
||
|
{
|
||
|
asn1Out.WriteEncodingDL(withID, Asn1Tags.UtcTime, GetOctets());
|
||
|
}
|
||
|
|
||
|
protected override bool Asn1Equals(
|
||
|
Asn1Object asn1Object)
|
||
|
{
|
||
|
DerUtcTime other = asn1Object as DerUtcTime;
|
||
|
|
||
|
if (other == null)
|
||
|
return false;
|
||
|
|
||
|
return this.time.Equals(other.time);
|
||
|
}
|
||
|
|
||
|
protected override int Asn1GetHashCode()
|
||
|
{
|
||
|
return time.GetHashCode();
|
||
|
}
|
||
|
|
||
|
public override string ToString()
|
||
|
{
|
||
|
return time;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#pragma warning restore
|
||
|
#endif
|