summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2022-10-27 20:10:48 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2022-10-27 20:10:48 +0700
commitee804df4e9fce47ff92a39524646c4aba0a90ddc (patch)
treecd52aa3902db7502db774b9fb7fbe1d956d765df
parentRefactoring in Bcpg.Sig (diff)
downloadBouncyCastle.NET-ed25519-ee804df4e9fce47ff92a39524646c4aba0a90ddc.tar.xz
DateTimeUtilities improvements:
- DateTimeToUnixMs converts to UTC
- UnixMsToDateTime checks input range
-rw-r--r--crypto/src/bcpg/SignaturePacket.cs10
-rw-r--r--crypto/src/security/JksStore.cs6
-rw-r--r--crypto/src/util/date/DateTimeUtilities.cs58
-rw-r--r--crypto/test/src/openpgp/test/DSA2Test.cs10
-rw-r--r--crypto/test/src/openpgp/test/PGPDSAElGamalTest.cs9
-rw-r--r--crypto/test/src/openpgp/test/PGPDSATest.cs17
-rw-r--r--crypto/test/src/openpgp/test/PGPPBETest.cs16
-rw-r--r--crypto/test/src/openpgp/test/PGPRSATest.cs18
-rw-r--r--crypto/test/src/openpgp/test/PGPSignatureTest.cs4
9 files changed, 81 insertions, 67 deletions
diff --git a/crypto/src/bcpg/SignaturePacket.cs b/crypto/src/bcpg/SignaturePacket.cs
index 3256ee35e..dd9cc78e3 100644
--- a/crypto/src/bcpg/SignaturePacket.cs
+++ b/crypto/src/bcpg/SignaturePacket.cs
@@ -237,7 +237,7 @@ namespace Org.BouncyCastle.Bcpg
 
 			if (hashedData != null)
 			{
-				setCreationTime();
+				SetCreationTime();
 			}
 		}
 
@@ -446,18 +446,18 @@ namespace Org.BouncyCastle.Bcpg
 			return sOut.ToArray();
 		}
 
-		private void setCreationTime()
+		private void SetCreationTime()
 		{
 			foreach (SignatureSubpacket p in hashedData)
 			{
-				if (p is SignatureCreationTime)
+				if (p is SignatureCreationTime signatureCreationTime)
 				{
-                    creationTime = DateTimeUtilities.DateTimeToUnixMs(
-						((SignatureCreationTime)p).GetTime());
+                    creationTime = DateTimeUtilities.DateTimeToUnixMs(signatureCreationTime.GetTime());
 					break;
 				}
 			}
 		}
+
         public static SignaturePacket FromByteArray(byte[] data)
         {
             BcpgInputStream input = BcpgInputStream.Wrap(new MemoryStream(data));
diff --git a/crypto/src/security/JksStore.cs b/crypto/src/security/JksStore.cs
index 69ade11af..30b21fad2 100644
--- a/crypto/src/security/JksStore.cs
+++ b/crypto/src/security/JksStore.cs
@@ -461,8 +461,7 @@ namespace Org.BouncyCastle.Security
         private static DateTime ReadDateTime(BinaryReader br)
         {
             long unixMS = BinaryReaders.ReadInt64BigEndian(br);
-            DateTime unix = DateTimeUtilities.UnixMsToDateTime(unixMS);
-            return new DateTime(unix.Ticks, DateTimeKind.Utc);
+            return DateTimeUtilities.UnixMsToDateTime(unixMS);
         }
 
         private static X509Certificate ReadTypedCertificate(BinaryReader br, int storeVersion)
@@ -517,8 +516,7 @@ namespace Org.BouncyCastle.Security
 
         private static void WriteDateTime(BinaryWriter bw, DateTime dateTime)
         {
-            DateTime utc = dateTime.ToUniversalTime();
-            long unixMS = DateTimeUtilities.DateTimeToUnixMs(utc);
+            long unixMS = DateTimeUtilities.DateTimeToUnixMs(dateTime);
             BinaryWriters.WriteInt64BigEndian(bw, unixMS);
         }
 
diff --git a/crypto/src/util/date/DateTimeUtilities.cs b/crypto/src/util/date/DateTimeUtilities.cs
index 72e5123a2..3660e29c2 100644
--- a/crypto/src/util/date/DateTimeUtilities.cs
+++ b/crypto/src/util/date/DateTimeUtilities.cs
@@ -2,38 +2,48 @@ using System;
 
 namespace Org.BouncyCastle.Utilities.Date
 {
-	public class DateTimeUtilities
+	public static class DateTimeUtilities
 	{
-		public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public static readonly DateTime UnixEpoch = DateTime.UnixEpoch;
+#else
+        public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+#endif
 
-		private DateTimeUtilities()
-		{
-		}
+        public static readonly long MaxUnixMs =
+            (DateTime.MaxValue.Ticks - UnixEpoch.Ticks) / TimeSpan.TicksPerMillisecond;
+        public static readonly long MinUnixMs = 0L;
 
-		/// <summary>
-		/// Return the number of milliseconds since the Unix epoch (1 Jan., 1970 UTC) for a given DateTime value.
-		/// </summary>
-		/// <param name="dateTime">A UTC DateTime value not before epoch.</param>
-		/// <returns>Number of whole milliseconds after epoch.</returns>
-		/// <exception cref="ArgumentException">'dateTime' is before epoch.</exception>
-		public static long DateTimeToUnixMs(
-			DateTime dateTime)
+        /// <summary>
+        /// Return the number of milliseconds since the Unix epoch (1 Jan., 1970 UTC) for a given DateTime value.
+        /// </summary>
+        /// <remarks>The DateTime value will be converted to UTC (using <see cref="DateTime.ToUniversalTime"/> before
+        /// conversion.</remarks>
+        /// <param name="dateTime">A DateTime value not before the epoch.</param>
+        /// <returns>Number of whole milliseconds after epoch.</returns>
+        /// <exception cref="ArgumentOutOfRangeException">'dateTime' is before the epoch.</exception>
+        public static long DateTimeToUnixMs(DateTime dateTime)
 		{
-			if (dateTime.CompareTo(UnixEpoch) < 0)
-				throw new ArgumentException("DateTime value may not be before the epoch", "dateTime");
+            DateTime utc = dateTime.ToUniversalTime();
+            if (utc.CompareTo(UnixEpoch) < 0)
+				throw new ArgumentOutOfRangeException(nameof(dateTime), "DateTime value may not be before the epoch");
 
-			return (dateTime.Ticks - UnixEpoch.Ticks) / TimeSpan.TicksPerMillisecond;
+			return (utc.Ticks - UnixEpoch.Ticks) / TimeSpan.TicksPerMillisecond;
 		}
 
-		/// <summary>
-		/// Create a DateTime value from the number of milliseconds since the Unix epoch (1 Jan., 1970 UTC).
-		/// </summary>
-		/// <param name="unixMs">Number of milliseconds since the epoch.</param>
-		/// <returns>A UTC DateTime value</returns>
-		public static DateTime UnixMsToDateTime(
-			long unixMs)
+        /// <summary>
+        /// Create a UTC DateTime value from the number of milliseconds since the Unix epoch (1 Jan., 1970 UTC).
+        /// </summary>
+        /// <param name="unixMs">Number of milliseconds since the epoch.</param>
+        /// <returns>A UTC DateTime value</returns>
+        /// <exception cref="ArgumentOutOfRangeException">'unixMs' is before 'MinUnixMs' or after 'MaxUnixMs'.
+        /// </exception>
+        public static DateTime UnixMsToDateTime(long unixMs)
 		{
-			return new DateTime(unixMs * TimeSpan.TicksPerMillisecond + UnixEpoch.Ticks, DateTimeKind.Utc);
+			if (unixMs < MinUnixMs || unixMs > MaxUnixMs)
+				throw new ArgumentOutOfRangeException(nameof(unixMs));
+
+            return new DateTime(unixMs * TimeSpan.TicksPerMillisecond + UnixEpoch.Ticks, DateTimeKind.Utc);
 		}
 
 		/// <summary>
diff --git a/crypto/test/src/openpgp/test/DSA2Test.cs b/crypto/test/src/openpgp/test/DSA2Test.cs
index 883ae317f..507afceae 100644
--- a/crypto/test/src/openpgp/test/DSA2Test.cs
+++ b/crypto/test/src/openpgp/test/DSA2Test.cs
@@ -4,6 +4,7 @@ using System.Text;
 
 using NUnit.Framework;
 
+using Org.BouncyCastle.Utilities.Date;
 using Org.BouncyCastle.Utilities.Test;
 
 namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
@@ -126,16 +127,15 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
 
 			PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
 
-//			Date testDate = new Date((System.currentTimeMillis() / 1000) * 1000);
-			DateTime testDate = new DateTime(
-				(DateTime.UtcNow.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond);
+			DateTime modificationTime = DateTimeUtilities.UnixMsToDateTime(
+				DateTimeUtilities.CurrentUnixMs() / 1000 * 1000);
 
 			Stream lOut = lGen.Open(
 				new UncloseableStream(bcOut),
 				PgpLiteralData.Binary,
 				"_CONSOLE",
 				dataBytes.Length,
-				testDate);
+				modificationTime);
 
 			int ch;
 			while ((ch = testIn.ReadByte()) >= 0)
@@ -156,7 +156,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
 			Assert.AreEqual(PublicKeyAlgorithmTag.Dsa, ops.KeyAlgorithm);
 
 			PgpLiteralData          p2 = (PgpLiteralData)pgpFact.NextPgpObject();
-			if (!p2.ModificationTime.Equals(testDate))
+			if (!p2.ModificationTime.Equals(modificationTime))
 			{
 				Assert.Fail("Modification time not preserved");
 			}
diff --git a/crypto/test/src/openpgp/test/PGPDSAElGamalTest.cs b/crypto/test/src/openpgp/test/PGPDSAElGamalTest.cs
index 1b1f5b6db..07c4d7eb6 100644
--- a/crypto/test/src/openpgp/test/PGPDSAElGamalTest.cs
+++ b/crypto/test/src/openpgp/test/PGPDSAElGamalTest.cs
@@ -141,13 +141,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
 
 			PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
 
-			DateTime testDateTime = new DateTime(1973, 7, 27);
-			Stream lOut = lGen.Open(
+            DateTime modificationTime = new DateTime(1973, 7, 27, 0, 0, 0, DateTimeKind.Utc);
+
+            Stream lOut = lGen.Open(
 				new UncloseableStream(bcOut),
 				PgpLiteralData.Binary,
 				"_CONSOLE",
 				dataBytes.Length,
-				testDateTime);
+                modificationTime);
 
 			int ch;
 			while ((ch = testIn.ReadByte()) >= 0)
@@ -176,7 +177,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
 			PgpOnePassSignature ops = p1[0];
 
 			PgpLiteralData p2 = (PgpLiteralData)pgpFact.NextPgpObject();
-			if (!p2.ModificationTime.Equals(testDateTime))
+			if (!p2.ModificationTime.Equals(modificationTime))
 			{
 				Fail("Modification time not preserved");
 			}
diff --git a/crypto/test/src/openpgp/test/PGPDSATest.cs b/crypto/test/src/openpgp/test/PGPDSATest.cs
index d5ef8b5e9..70aca8e1f 100644
--- a/crypto/test/src/openpgp/test/PGPDSATest.cs
+++ b/crypto/test/src/openpgp/test/PGPDSATest.cs
@@ -305,13 +305,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
 
             PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
 
-			DateTime testDateTime = new DateTime(1973, 7, 27);
+			DateTime modificationTime = new DateTime(1973, 7, 27, 0, 0, 0, DateTimeKind.Utc);
+
 			Stream lOut = lGen.Open(
 				new UncloseableStream(bcOut),
 				PgpLiteralData.Binary,
 				"_CONSOLE",
 				dataBytes.Length,
-				testDateTime);
+				modificationTime);
 
 			int ch;
             while ((ch = testIn.ReadByte()) >= 0)
@@ -335,7 +336,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
             PgpOnePassSignature ops = p1[0];
 
             PgpLiteralData p2 = (PgpLiteralData) pgpFact.NextPgpObject();
-			if (!p2.ModificationTime.Equals(testDateTime))
+			if (!p2.ModificationTime.Equals(modificationTime))
 			{
 				Fail("Modification time not preserved");
 			}
@@ -429,13 +430,15 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
             sGen.GenerateOnePassVersion(false).Encode(bcOut);
 
             PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
-			DateTime testDateTime = new DateTime(1973, 7, 27);
-			Stream lOut = lGen.Open(
+
+            DateTime modificationTime = new DateTime(1973, 7, 27, 0, 0, 0, DateTimeKind.Utc);
+            
+            Stream lOut = lGen.Open(
 				new UncloseableStream(bcOut),
 				PgpLiteralData.Text,
 				"_CONSOLE",
 				dataBytes.Length,
-				testDateTime);
+                modificationTime);
 
 			while ((ch = testIn.ReadByte()) >= 0)
             {
@@ -463,7 +466,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
             ops = p1[0];
 
             p2 = (PgpLiteralData) pgpFact.NextPgpObject();
-			if (!p2.ModificationTime.Equals(testDateTime))
+			if (!p2.ModificationTime.Equals(modificationTime))
 			{
 				Fail("Modification time not preserved");
 			}
diff --git a/crypto/test/src/openpgp/test/PGPPBETest.cs b/crypto/test/src/openpgp/test/PGPPBETest.cs
index df40e1ef2..6b3718ecc 100644
--- a/crypto/test/src/openpgp/test/PGPPBETest.cs
+++ b/crypto/test/src/openpgp/test/PGPPBETest.cs
@@ -16,7 +16,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
     public class PgpPbeTest
 		: SimpleTest
     {
-		private static readonly DateTime TestDateTime = new DateTime(2003, 8, 29, 23, 35, 11, 0);
+		private static readonly DateTime ModificationTime = new DateTime(2003, 8, 29, 23, 35, 11, DateTimeKind.Utc);
 
 		private static readonly byte[] enc1 = Base64.Decode(
             "jA0EAwMC5M5wWBP2HBZgySvUwWFAmMRLn7dWiZN6AkQMvpE3b6qwN3SSun7zInw2"
@@ -66,9 +66,9 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
                 Fail("wrong filename in packet");
             }
 
-			if (!ld.ModificationTime.Equals(TestDateTime))
+			if (!ld.ModificationTime.Equals(ModificationTime))
 			{
-				Fail("wrong modification time in packet: " + ld.ModificationTime + " vs " + TestDateTime);
+				Fail("wrong modification time in packet: " + ld.ModificationTime + " vs " + ModificationTime);
 			}
 
 			Stream unc = ld.GetInputStream();
@@ -104,9 +104,9 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
 			{
 				Fail("wrong filename in packet");
 			}
-			if (!ld.ModificationTime.Equals(TestDateTime))
+			if (!ld.ModificationTime.Equals(ModificationTime))
 			{
-				Fail("wrong modification time in packet: " + ld.ModificationTime.Ticks + " " + TestDateTime.Ticks);
+				Fail("wrong modification time in packet: " + ld.ModificationTime.Ticks + " " + ModificationTime.Ticks);
 			}
 
 			Stream unc = ld.GetInputStream();
@@ -154,7 +154,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
                 PgpLiteralData.Binary,
                 PgpLiteralData.Console,
                 text.Length,
-                TestDateTime);
+                ModificationTime);
 
 			ldOut.Write(text, 0, text.Length);
 			ldOut.Close();
@@ -222,7 +222,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
 				new UncloseableStream(comOut),
                 PgpLiteralData.Binary,
                 PgpLiteralData.Console,
-                TestDateTime,
+                ModificationTime,
                 new byte[16]);
 
             ldOut.Write(test, 0, test.Length);
@@ -317,7 +317,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
 				PgpLiteralData.Binary,
 				PgpLiteralData.Console,
 				msg.Length,
-				TestDateTime);
+                ModificationTime);
 
 			ldOut.Write(msg, 0, msg.Length);
 
diff --git a/crypto/test/src/openpgp/test/PGPRSATest.cs b/crypto/test/src/openpgp/test/PGPRSATest.cs
index 9d1dedd95..fa573de65 100644
--- a/crypto/test/src/openpgp/test/PGPRSATest.cs
+++ b/crypto/test/src/openpgp/test/PGPRSATest.cs
@@ -967,9 +967,9 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
 
             PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
 
-            DateTime testDateTime = new DateTime(1973, 7, 27);
+            DateTime modificationTime = new DateTime(1973, 7, 27, 0, 0, 0, DateTimeKind.Utc);
             Stream lOut = lGen.Open(new UncloseableStream(bcOut), PgpLiteralData.Binary, "_CONSOLE",
-                dataBytes.Length, testDateTime);
+                dataBytes.Length, modificationTime);
 
             // TODO Need a stream object to automatically call Update?
             // (via ISigner implementation of PgpSignatureGenerator)
@@ -999,7 +999,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
             ops = p1[0];
 
             p2 = (PgpLiteralData)pgpFact.NextPgpObject();
-            if (!p2.ModificationTime.Equals(testDateTime))
+            if (!p2.ModificationTime.Equals(modificationTime))
             {
                 Fail("Modification time not preserved");
             }
@@ -1045,7 +1045,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
                 PgpLiteralData.Binary,
                 "_CONSOLE",
                 dataBytes.Length,
-                testDateTime);
+                modificationTime);
 
             // TODO Need a stream object to automatically call Update?
             // (via ISigner implementation of PgpSignatureGenerator)
@@ -1075,7 +1075,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
             ops = p1[0];
 
             p2 = (PgpLiteralData)pgpFact.NextPgpObject();
-            if (!p2.ModificationTime.Equals(testDateTime))
+            if (!p2.ModificationTime.Equals(modificationTime))
             {
                 Fail("Modification time not preserved");
             }
@@ -1139,13 +1139,15 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
             sGen.GenerateOnePassVersion(false).Encode(bcOut);
 
             PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
-            DateTime testDateTime = new DateTime(1973, 7, 27);
+
+            DateTime modificationTime = new DateTime(1973, 7, 27, 0, 0, 0, DateTimeKind.Utc);
+
             Stream lOut = lGen.Open(
                 new UncloseableStream(bcOut),
                 PgpLiteralData.Binary,
                 "_CONSOLE",
                 dataBytes.Length,
-                testDateTime);
+                modificationTime);
 
             // TODO Need a stream object to automatically call Update?
             // (via ISigner implementation of PgpSignatureGenerator)
@@ -1176,7 +1178,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
             PgpOnePassSignature ops = p1[0];
 
             PgpLiteralData p2 = (PgpLiteralData)pgpFact.NextPgpObject();
-            if (!p2.ModificationTime.Equals(testDateTime))
+            if (!p2.ModificationTime.Equals(modificationTime))
             {
                 Fail("Modification time not preserved");
             }
diff --git a/crypto/test/src/openpgp/test/PGPSignatureTest.cs b/crypto/test/src/openpgp/test/PGPSignatureTest.cs
index e43eb5d8a..ea9df9567 100644
--- a/crypto/test/src/openpgp/test/PGPSignatureTest.cs
+++ b/crypto/test/src/openpgp/test/PGPSignatureTest.cs
@@ -551,7 +551,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
 
             hashedGen = new PgpSignatureSubpacketGenerator();
 
-            DateTime creationTime = new DateTime(1973, 7, 27);
+            DateTime creationTime = new DateTime(1973, 7, 27, 0, 0, 0, DateTimeKind.Utc);
             hashedGen.SetSignatureCreationTime(false, creationTime);
 
             sGen.SetHashedSubpackets(hashedGen.Generate());
@@ -997,7 +997,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
 
             PgpSignature sig = sGen.Generate();
 
-            if (sig.CreationTime == DateTimeUtilities.UnixMsToDateTime(0))
+            if (DateTimeUtilities.DateTimeToUnixMs(sig.CreationTime) == 0)
             {
                 Fail("creation time not set in v3 signature");
             }