summary refs log tree commit diff
path: root/crypto
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2022-10-25 23:32:48 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2022-10-25 23:32:48 +0700
commit5cfc4eae7e78d0299f5ebf47b45109805221a2d6 (patch)
tree91ae5b56a4ab011b38433066fba923e4a53ec3ae /crypto
parentRefactor Pqc test configs (diff)
downloadBouncyCastle.NET-ed25519-5cfc4eae7e78d0299f5ebf47b45109805221a2d6.tar.xz
Add Asn1UtcTime and use
Diffstat (limited to 'crypto')
-rw-r--r--crypto/src/asn1/Asn1InputStream.cs2
-rw-r--r--crypto/src/asn1/Asn1UniversalTypes.cs2
-rw-r--r--crypto/src/asn1/Asn1UtcTime.cs264
-rw-r--r--crypto/src/asn1/DerUTCTime.cs259
-rw-r--r--crypto/src/asn1/cms/Time.cs37
-rw-r--r--crypto/src/asn1/esf/CrlIdentifier.cs47
-rw-r--r--crypto/src/asn1/util/Asn1Dump.cs2
-rw-r--r--crypto/src/asn1/x509/TBSCertList.cs2
-rw-r--r--crypto/src/asn1/x509/Time.cs37
-rw-r--r--crypto/src/asn1/x509/V1TBSCertificateGenerator.cs4
-rw-r--r--crypto/src/asn1/x509/V2TBSCertListGenerator.cs6
-rw-r--r--crypto/src/asn1/x509/V3TBSCertificateGenerator.cs4
12 files changed, 338 insertions, 328 deletions
diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs
index e7caee9bd..0e772010f 100644
--- a/crypto/src/asn1/Asn1InputStream.cs
+++ b/crypto/src/asn1/Asn1InputStream.cs
@@ -452,7 +452,7 @@ namespace Org.BouncyCastle.Asn1
             case Asn1Tags.UniversalString:
                 return DerUniversalString.CreatePrimitive(bytes);
             case Asn1Tags.UtcTime:
-                return DerUtcTime.CreatePrimitive(bytes);
+                return Asn1UtcTime.CreatePrimitive(bytes);
             case Asn1Tags.Utf8String:
                 return DerUtf8String.CreatePrimitive(bytes);
             case Asn1Tags.VideotexString:
diff --git a/crypto/src/asn1/Asn1UniversalTypes.cs b/crypto/src/asn1/Asn1UniversalTypes.cs
index d188988f6..f5b5d0498 100644
--- a/crypto/src/asn1/Asn1UniversalTypes.cs
+++ b/crypto/src/asn1/Asn1UniversalTypes.cs
@@ -49,7 +49,7 @@ namespace Org.BouncyCastle.Asn1
             case Asn1Tags.IA5String:                // [UNIVERSAL 22] IMPLICIT OCTET STRING (encode as if)
                 return DerIA5String.Meta.Instance;
             case Asn1Tags.UtcTime:                  // [UNIVERSAL 23] IMPLICIT VisibleString (restricted values)
-                return DerUtcTime.Meta.Instance;
+                return Asn1UtcTime.Meta.Instance;
             case Asn1Tags.GeneralizedTime:          // [UNIVERSAL 24] IMPLICIT VisibleString (restricted values)
                 return Asn1GeneralizedTime.Meta.Instance;
             case Asn1Tags.GraphicString:            // [UNIVERSAL 25] IMPLICIT OCTET STRING (encode as if)
diff --git a/crypto/src/asn1/Asn1UtcTime.cs b/crypto/src/asn1/Asn1UtcTime.cs
new file mode 100644
index 000000000..05de430c4
--- /dev/null
+++ b/crypto/src/asn1/Asn1UtcTime.cs
@@ -0,0 +1,264 @@
+using System;
+using System.Globalization;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    /**
+     * UTC time object.
+     */
+    public class Asn1UtcTime
+        : Asn1Object
+    {
+        internal class Meta : Asn1UniversalType
+        {
+            internal static readonly Asn1UniversalType Instance = new Meta();
+
+            private Meta() : base(typeof(Asn1UtcTime), Asn1Tags.UtcTime) {}
+
+            internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
+            {
+                return CreatePrimitive(octetString.GetOctets());
+            }
+        }
+
+		/**
+         * return a UTC Time from the passed in object.
+         *
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static Asn1UtcTime GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+
+            if (obj is Asn1UtcTime asn1UtcTime)
+                return asn1UtcTime;
+
+            if (obj is IAsn1Convertible asn1Convertible)
+            {
+                Asn1Object asn1Object = asn1Convertible.ToAsn1Object();
+                if (asn1Object is Asn1UtcTime converted)
+                    return converted;
+            }
+            else if (obj is byte[] bytes)
+            {
+                try
+                {
+                    return (Asn1UtcTime)Meta.Instance.FromByteArray(bytes);
+                }
+                catch (IOException e)
+                {
+                    throw new ArgumentException("failed to construct UTC time from byte[]: " + e.Message);
+                }
+            }
+
+            throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj));
+        }
+
+        /**
+         * return a UTC Time from a tagged object.
+         *
+         * @param taggedObject the tagged object holding the object we want
+         * @param declaredExplicit true if the object is meant to be explicitly tagged false otherwise.
+         * @exception ArgumentException if the tagged object cannot be converted.
+         */
+        public static Asn1UtcTime GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return (Asn1UtcTime)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
+        }
+
+        private readonly string time;
+
+        /**
+         * 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 Asn1UtcTime(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 Asn1UtcTime(DateTime time)
+        {
+            this.time = time.ToUniversalTime().ToString("yyMMddHHmmss", CultureInfo.InvariantCulture) + "Z";
+        }
+
+		internal Asn1UtcTime(byte[] contents)
+        {
+            //
+            // explicitly convert to characters
+            //
+            this.time = Strings.FromAsciiByteArray(contents);
+        }
+
+		/**
+		 * 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);
+					}
+				}
+			}
+        }
+
+		/// <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;
+			}
+		}
+
+        internal byte[] GetOctets()
+        {
+            return Strings.ToAsciiByteArray(time);
+        }
+
+        internal override IAsn1Encoding GetEncoding(int encoding)
+        {
+            return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.UtcTime, GetOctets());
+        }
+
+        internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo)
+        {
+            return new PrimitiveEncoding(tagClass, tagNo, GetOctets());
+        }
+
+        protected override bool Asn1Equals(Asn1Object asn1Object)
+		{
+            if (!(asn1Object is Asn1UtcTime that))
+                return false;
+
+            return this.time == that.time;
+        }
+
+		protected override int Asn1GetHashCode()
+		{
+            return time.GetHashCode();
+        }
+
+		public override string ToString()
+		{
+			return time;
+		}
+
+        internal static Asn1UtcTime CreatePrimitive(byte[] contents)
+        {
+            return new Asn1UtcTime(contents);
+        }
+    }
+}
diff --git a/crypto/src/asn1/DerUTCTime.cs b/crypto/src/asn1/DerUTCTime.cs
index 7f7756d49..089285367 100644
--- a/crypto/src/asn1/DerUTCTime.cs
+++ b/crypto/src/asn1/DerUTCTime.cs
@@ -1,274 +1,25 @@
 using System;
-using System.Globalization;
-using System.IO;
-
-using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Asn1
 {
-    /**
-     * UTC time object.
-     */
     public class DerUtcTime
-        : Asn1Object
+        : Asn1UtcTime
     {
-        internal class Meta : Asn1UniversalType
-        {
-            internal static readonly Asn1UniversalType Instance = new Meta();
-
-            private Meta() : base(typeof(DerUtcTime), Asn1Tags.UtcTime) {}
-
-            internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
-            {
-                return CreatePrimitive(octetString.GetOctets());
-            }
-        }
-
-		/**
-         * return a 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;
-            }
-            else if (obj is IAsn1Convertible)
-            {
-                Asn1Object asn1Object = ((IAsn1Convertible)obj).ToAsn1Object();
-                if (asn1Object is DerUtcTime)
-                    return (DerUtcTime)asn1Object;
-            }
-            else if (obj is byte[])
-            {
-                try
-                {
-                    return (DerUtcTime)Meta.Instance.FromByteArray((byte[])obj);
-                }
-                catch (IOException e)
-                {
-                    throw new ArgumentException("failed to construct UTC time from byte[]: " + e.Message);
-                }
-            }
-
-            throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj));
-        }
-
-        /**
-         * return a UTC Time from a tagged object.
-         *
-         * @param taggedObject the tagged object holding the object we want
-         * @param declaredExplicit 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 taggedObject, bool declaredExplicit)
-        {
-            return (DerUtcTime)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
-        }
-
-        private readonly string time;
-
-        /**
-         * 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)
+			: base(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)
+			: base(time)
         {
-            this.time = time.ToUniversalTime().ToString("yyMMddHHmmss", CultureInfo.InvariantCulture) + "Z";
         }
 
 		internal DerUtcTime(byte[] contents)
+			: base(contents)
         {
-            //
-            // explicitly convert to characters
-            //
-            this.time = Strings.FromAsciiByteArray(contents);
-        }
-
-//		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);
-					}
-				}
-			}
-        }
-
-		/// <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 IAsn1Encoding GetEncoding(int encoding)
-        {
-            return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.UtcTime, GetOctets());
-        }
-
-        internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo)
-        {
-            return new PrimitiveEncoding(tagClass, tagNo, GetOctets());
-        }
-
-        protected override bool Asn1Equals(Asn1Object asn1Object)
-		{
-			DerUtcTime that = asn1Object as DerUtcTime;
-            return null != that
-                && this.time.Equals(that.time);
         }
 
-		protected override int Asn1GetHashCode()
-		{
-            return time.GetHashCode();
-        }
-
-		public override string ToString()
-		{
-			return time;
-		}
-
-        internal static DerUtcTime CreatePrimitive(byte[] contents)
-        {
-            return new DerUtcTime(contents);
-        }
+        // TODO: create proper DER encoding.
     }
 }
diff --git a/crypto/src/asn1/cms/Time.cs b/crypto/src/asn1/cms/Time.cs
index e8a6905ad..89f1e4dae 100644
--- a/crypto/src/asn1/cms/Time.cs
+++ b/crypto/src/asn1/cms/Time.cs
@@ -22,7 +22,7 @@ namespace Org.BouncyCastle.Asn1.Cms
         {
             if (time == null)
                 throw new ArgumentNullException("time");
-            if (!(time is DerUtcTime) && !(time is Asn1GeneralizedTime))
+            if (!(time is Asn1UtcTime) && !(time is Asn1GeneralizedTime))
                 throw new ArgumentException("unknown object passed to Time");
 
             this.time = time;
@@ -49,15 +49,16 @@ namespace Org.BouncyCastle.Asn1.Cms
             }
         }
 
-		public static Time GetInstance(
-            object obj)
+		public static Time GetInstance(object obj)
         {
-            if (obj == null || obj is Time)
-                return (Time)obj;
-			if (obj is DerUtcTime)
-                return new Time((DerUtcTime)obj);
-			if (obj is Asn1GeneralizedTime)
-                return new Time((Asn1GeneralizedTime)obj);
+            if (obj == null)
+                return null;
+            if (obj is Time time)
+                return time;
+			if (obj is Asn1UtcTime utcTime)
+                return new Time(utcTime);
+			if (obj is Asn1GeneralizedTime generalizedTime)
+                return new Time(generalizedTime);
 
             throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj");
         }
@@ -66,14 +67,10 @@ namespace Org.BouncyCastle.Asn1.Cms
         {
 			get
 			{
-				if (time is DerUtcTime)
-				{
-					return ((DerUtcTime)time).AdjustedTimeString;
-				}
-				else
-				{
-					return ((Asn1GeneralizedTime)time).GetTime();
-				}
+				if (time is Asn1UtcTime utcTime)
+					return utcTime.AdjustedTimeString;
+
+                return ((Asn1GeneralizedTime)time).GetTime();
 			}
         }
 
@@ -83,10 +80,8 @@ namespace Org.BouncyCastle.Asn1.Cms
 			{
 				try
 				{
-					if (time is DerUtcTime)
-					{
-						return ((DerUtcTime)time).ToAdjustedDateTime();
-					}
+					if (time is Asn1UtcTime utcTime)
+						return utcTime.ToAdjustedDateTime();
 
 					return ((Asn1GeneralizedTime)time).ToDateTime();
 				}
diff --git a/crypto/src/asn1/esf/CrlIdentifier.cs b/crypto/src/asn1/esf/CrlIdentifier.cs
index a8e40c870..44c99170c 100644
--- a/crypto/src/asn1/esf/CrlIdentifier.cs
+++ b/crypto/src/asn1/esf/CrlIdentifier.cs
@@ -1,5 +1,5 @@
 using System;
-
+using System.Reflection;
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Utilities;
@@ -21,7 +21,7 @@ namespace Org.BouncyCastle.Asn1.Esf
 		: Asn1Encodable
 	{
 		private readonly X509Name	crlIssuer;
-		private readonly DerUtcTime	crlIssuedTime;
+		private readonly Asn1UtcTime crlIssuedTime;
 		private readonly DerInteger	crlNumber;
 
 		public static CrlIdentifier GetInstance(
@@ -48,7 +48,7 @@ namespace Org.BouncyCastle.Asn1.Esf
 				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
 
 			this.crlIssuer = X509Name.GetInstance(seq[0]);
-			this.crlIssuedTime = DerUtcTime.GetInstance(seq[1]);
+			this.crlIssuedTime = Asn1UtcTime.GetInstance(seq[1]);
 
 			if (seq.Count > 2)
 			{
@@ -56,31 +56,36 @@ namespace Org.BouncyCastle.Asn1.Esf
 			}
 		}
 
-		public CrlIdentifier(
-			X509Name	crlIssuer,
-			DateTime	crlIssuedTime)
-			: this(crlIssuer, crlIssuedTime, null)
+        public CrlIdentifier(X509Name crlIssuer, DateTime crlIssuedTime)
+            : this(crlIssuer, crlIssuedTime, null)
 		{
 		}
 
-		public CrlIdentifier(
-			X509Name	crlIssuer,
-			DateTime	crlIssuedTime,
-			BigInteger	crlNumber)
+		public CrlIdentifier(X509Name crlIssuer, DateTime crlIssuedTime, BigInteger crlNumber)
+			: this(crlIssuer, new Asn1UtcTime(crlIssuedTime), crlNumber)
 		{
-			if (crlIssuer == null)
-				throw new ArgumentNullException("crlIssuer");
+		}
 
-			this.crlIssuer = crlIssuer;
-			this.crlIssuedTime = new DerUtcTime(crlIssuedTime);
+        public CrlIdentifier(X509Name crlIssuer, Asn1UtcTime crlIssuedTime)
+            : this(crlIssuer, crlIssuedTime, null)
+        {
+        }
 
-			if (crlNumber != null)
-			{
-				this.crlNumber = new DerInteger(crlNumber);
-			}
-		}
+        public CrlIdentifier(X509Name crlIssuer, Asn1UtcTime crlIssuedTime, BigInteger crlNumber)
+        {
+            if (crlIssuer == null)
+                throw new ArgumentNullException(nameof(crlIssuer));
+
+            this.crlIssuer = crlIssuer;
+            this.crlIssuedTime = crlIssuedTime;
+
+            if (null != crlNumber)
+            {
+                this.crlNumber = new DerInteger(crlNumber);
+            }
+        }
 
-		public X509Name CrlIssuer
+        public X509Name CrlIssuer
 		{
 			get { return crlIssuer; }
 		}
diff --git a/crypto/src/asn1/util/Asn1Dump.cs b/crypto/src/asn1/util/Asn1Dump.cs
index 73586cf9b..6c005f512 100644
--- a/crypto/src/asn1/util/Asn1Dump.cs
+++ b/crypto/src/asn1/util/Asn1Dump.cs
@@ -206,7 +206,7 @@ namespace Org.BouncyCastle.Asn1.Utilities
                 buf.Append(indent);
                 buf.AppendLine("VideotexString(" + videotexString.GetString() + ")");
             }
-            else if (obj is DerUtcTime utcTime)
+            else if (obj is Asn1UtcTime utcTime)
             {
                 buf.Append(indent);
                 buf.AppendLine("UTCTime(" + utcTime.TimeString + ")");
diff --git a/crypto/src/asn1/x509/TBSCertList.cs b/crypto/src/asn1/x509/TBSCertList.cs
index 865cfdd3d..2b288850f 100644
--- a/crypto/src/asn1/x509/TBSCertList.cs
+++ b/crypto/src/asn1/x509/TBSCertList.cs
@@ -193,7 +193,7 @@ namespace Org.BouncyCastle.Asn1.X509
             thisUpdate = Time.GetInstance(seq[seqPos++]);
 
 			if (seqPos < seq.Count
-                && (seq[seqPos] is DerUtcTime
+                && (seq[seqPos] is Asn1UtcTime
                    || seq[seqPos] is Asn1GeneralizedTime
                    || seq[seqPos] is Time))
             {
diff --git a/crypto/src/asn1/x509/Time.cs b/crypto/src/asn1/x509/Time.cs
index 791f08053..1a6ac15c0 100644
--- a/crypto/src/asn1/x509/Time.cs
+++ b/crypto/src/asn1/x509/Time.cs
@@ -22,7 +22,7 @@ namespace Org.BouncyCastle.Asn1.X509
         {
             if (time == null)
                 throw new ArgumentNullException("time");
-            if (!(time is DerUtcTime) && !(time is Asn1GeneralizedTime))
+            if (!(time is Asn1UtcTime) && !(time is Asn1GeneralizedTime))
                 throw new ArgumentException("unknown object passed to Time");
 
             this.time = time;
@@ -49,25 +49,24 @@ namespace Org.BouncyCastle.Asn1.X509
             }
         }
 
-        public static Time GetInstance(
-            object obj)
+        public static Time GetInstance(object obj)
         {
-            if (obj == null || obj is Time)
-                return (Time)obj;
-            if (obj is DerUtcTime)
-                return new Time((DerUtcTime)obj);
-            if (obj is Asn1GeneralizedTime)
-                return new Time((Asn1GeneralizedTime)obj);
+            if (obj == null)
+                return null;
+            if (obj is Time time)
+                return time;
+            if (obj is Asn1UtcTime utcTime)
+                return new Time(utcTime);
+            if (obj is Asn1GeneralizedTime generalizedTime)
+                return new Time(generalizedTime);
 
             throw new ArgumentException("unknown object in factory: " + Platform.GetTypeName(obj), "obj");
         }
 
         public string GetTime()
         {
-            if (time is DerUtcTime)
-            {
-                return ((DerUtcTime)time).AdjustedTimeString;
-            }
+            if (time is Asn1UtcTime utcTime)
+                return utcTime.AdjustedTimeString;
 
             return ((Asn1GeneralizedTime)time).GetTime();
         }
@@ -80,14 +79,10 @@ namespace Org.BouncyCastle.Asn1.X509
         {
             try
             {
-                if (time is DerUtcTime)
-                {
-                    return ((DerUtcTime)time).ToAdjustedDateTime();
-                }
-                else
-                {
-                    return ((Asn1GeneralizedTime)time).ToDateTime();
-                }
+                if (time is Asn1UtcTime utcTime)
+                    return utcTime.ToAdjustedDateTime();
+
+                return ((Asn1GeneralizedTime)time).ToDateTime();
             }
             catch (FormatException e)
             {
diff --git a/crypto/src/asn1/x509/V1TBSCertificateGenerator.cs b/crypto/src/asn1/x509/V1TBSCertificateGenerator.cs
index 20b525a48..9cbff1ef0 100644
--- a/crypto/src/asn1/x509/V1TBSCertificateGenerator.cs
+++ b/crypto/src/asn1/x509/V1TBSCertificateGenerator.cs
@@ -56,7 +56,7 @@ namespace Org.BouncyCastle.Asn1.X509
         }
 
 		public void SetStartDate(
-            DerUtcTime startDate)
+            Asn1UtcTime startDate)
         {
             this.startDate = new Time(startDate);
         }
@@ -68,7 +68,7 @@ namespace Org.BouncyCastle.Asn1.X509
         }
 
 		public void SetEndDate(
-            DerUtcTime endDate)
+            Asn1UtcTime endDate)
         {
             this.endDate = new Time(endDate);
         }
diff --git a/crypto/src/asn1/x509/V2TBSCertListGenerator.cs b/crypto/src/asn1/x509/V2TBSCertListGenerator.cs
index 546dc91f9..aa1a0b95d 100644
--- a/crypto/src/asn1/x509/V2TBSCertListGenerator.cs
+++ b/crypto/src/asn1/x509/V2TBSCertListGenerator.cs
@@ -55,13 +55,13 @@ namespace Org.BouncyCastle.Asn1.X509
         }
 
 		public void SetThisUpdate(
-            DerUtcTime thisUpdate)
+            Asn1UtcTime thisUpdate)
         {
             this.thisUpdate = new Time(thisUpdate);
         }
 
 		public void SetNextUpdate(
-            DerUtcTime nextUpdate)
+            Asn1UtcTime nextUpdate)
         {
             this.nextUpdate = (nextUpdate != null)
 				?	new Time(nextUpdate)
@@ -90,7 +90,7 @@ namespace Org.BouncyCastle.Asn1.X509
 			crlEntries.Add(crlEntry);
 		}
 
-		public void AddCrlEntry(DerInteger userCertificate, DerUtcTime revocationDate, int reason)
+		public void AddCrlEntry(DerInteger userCertificate, Asn1UtcTime revocationDate, int reason)
 		{
 			AddCrlEntry(userCertificate, new Time(revocationDate), reason);
 		}
diff --git a/crypto/src/asn1/x509/V3TBSCertificateGenerator.cs b/crypto/src/asn1/x509/V3TBSCertificateGenerator.cs
index beb469a0d..544582ddb 100644
--- a/crypto/src/asn1/x509/V3TBSCertificateGenerator.cs
+++ b/crypto/src/asn1/x509/V3TBSCertificateGenerator.cs
@@ -58,7 +58,7 @@ namespace Org.BouncyCastle.Asn1.X509
         }
 
 		public void SetStartDate(
-            DerUtcTime startDate)
+            Asn1UtcTime startDate)
         {
             this.startDate = new Time(startDate);
         }
@@ -70,7 +70,7 @@ namespace Org.BouncyCastle.Asn1.X509
         }
 
 		public void SetEndDate(
-            DerUtcTime endDate)
+            Asn1UtcTime endDate)
         {
             this.endDate = new Time(endDate);
         }