From 8602d5fe29555ce04127619f6e958737933b2150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Fri, 14 Nov 2025 08:11:34 +0100 Subject: [PATCH] Bring CryptoHelper to the state of the art for .NET 10 --- CHANGELOG.md | 1 + .../Utilities/CryptographyHelper.cs | 70 ++++++++++++------- .../Utilities/CryptographyHelperTest.cs | 25 +++---- 3 files changed, 58 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e594ff..fc33a81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `DomainComparer` ordering alphabetically from TLD to sub-domain - `IPAddressComparer` able to compare IPv4 and IPv6 - `VersionStringComparer` to compare version strings (SemVer) +- `ASPNETCORE_APPL_PROXY` environment variable can be used on proxy configuration - Support for .NET 10.0 LTS ### Changed diff --git a/src/AMWD.Common/Utilities/CryptographyHelper.cs b/src/AMWD.Common/Utilities/CryptographyHelper.cs index 5967256..000eca1 100644 --- a/src/AMWD.Common/Utilities/CryptographyHelper.cs +++ b/src/AMWD.Common/Utilities/CryptographyHelper.cs @@ -171,7 +171,6 @@ namespace System.Security.Cryptography #region Static methods #region Encryption -#pragma warning disable SYSLIB0041 #region AES @@ -186,17 +185,22 @@ namespace System.Security.Cryptography byte[] salt = new byte[_saltLength]; Array.Copy(cipher, salt, _saltLength); -#if NET8_0_OR_GREATER - using var gen = new Rfc2898DeriveBytes(password, salt, 1000, HashAlgorithmName.SHA1); -#else - using var gen = new Rfc2898DeriveBytes(password, salt, 1000); -#endif using var aes = Aes.Create(); - aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; + +#if NET10_0_OR_GREATER + aes.Key = Rfc2898DeriveBytes.Pbkdf2(password, salt, 1000, HashAlgorithmName.SHA1, aes.KeySize / 8); + aes.IV = Rfc2898DeriveBytes.Pbkdf2(password, salt, 1000, HashAlgorithmName.SHA1, aes.BlockSize / 8); +#elif NET8_0_OR_GREATER + using var gen = new Rfc2898DeriveBytes(password, salt, 1000, HashAlgorithmName.SHA1); aes.Key = gen.GetBytes(aes.KeySize / 8); aes.IV = gen.GetBytes(aes.BlockSize / 8); +#else + using var gen = new Rfc2898DeriveBytes(password, salt, 1000); + aes.Key = gen.GetBytes(aes.KeySize / 8); + aes.IV = gen.GetBytes(aes.BlockSize / 8); +#endif using var ms = new MemoryStream(); using var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write); @@ -230,17 +234,22 @@ namespace System.Security.Cryptography { byte[] salt = GetRandomBytes(_saltLength); -#if NET8_0_OR_GREATER - using var gen = new Rfc2898DeriveBytes(password, salt, 1000, HashAlgorithmName.SHA1); -#else - using var gen = new Rfc2898DeriveBytes(password, salt, 1000); -#endif using var aes = Aes.Create(); - aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; + +#if NET10_0_OR_GREATER + aes.Key = Rfc2898DeriveBytes.Pbkdf2(password, salt, 1000, HashAlgorithmName.SHA1, aes.KeySize / 8); + aes.IV = Rfc2898DeriveBytes.Pbkdf2(password, salt, 1000, HashAlgorithmName.SHA1, aes.BlockSize / 8); +#elif NET8_0_OR_GREATER + using var gen = new Rfc2898DeriveBytes(password, salt, 1000, HashAlgorithmName.SHA1); aes.Key = gen.GetBytes(aes.KeySize / 8); aes.IV = gen.GetBytes(aes.BlockSize / 8); +#else + using var gen = new Rfc2898DeriveBytes(password, salt, 1000); + aes.Key = gen.GetBytes(aes.KeySize / 8); + aes.IV = gen.GetBytes(aes.BlockSize / 8); +#endif using var ms = new MemoryStream(); using var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write); @@ -280,17 +289,22 @@ namespace System.Security.Cryptography byte[] salt = new byte[_saltLength]; Array.Copy(cipher, salt, _saltLength); -#if NET8_0_OR_GREATER - using var gen = new Rfc2898DeriveBytes(password, salt, 1000, HashAlgorithmName.SHA1); -#else - using var gen = new Rfc2898DeriveBytes(password, salt, 1000); -#endif using var tdes = TripleDES.Create(); - tdes.Mode = CipherMode.CBC; tdes.Padding = PaddingMode.PKCS7; + +#if NET10_0_OR_GREATER + tdes.Key = Rfc2898DeriveBytes.Pbkdf2(password, salt, 1000, HashAlgorithmName.SHA1, tdes.KeySize / 8); + tdes.IV = Rfc2898DeriveBytes.Pbkdf2(password, salt, 1000, HashAlgorithmName.SHA1, tdes.BlockSize / 8); +#elif NET8_0_OR_GREATER + using var gen = new Rfc2898DeriveBytes(password, salt, 1000, HashAlgorithmName.SHA1); tdes.Key = gen.GetBytes(tdes.KeySize / 8); tdes.IV = gen.GetBytes(tdes.BlockSize / 8); +#else + using var gen = new Rfc2898DeriveBytes(password, salt, 1000); + tdes.Key = gen.GetBytes(tdes.KeySize / 8); + tdes.IV = gen.GetBytes(tdes.BlockSize / 8); +#endif using var ms = new MemoryStream(); using var cs = new CryptoStream(ms, tdes.CreateDecryptor(), CryptoStreamMode.Write); @@ -311,17 +325,22 @@ namespace System.Security.Cryptography { byte[] salt = GetRandomBytes(_saltLength); -#if NET8_0_OR_GREATER - using var gen = new Rfc2898DeriveBytes(password, salt, 1000, HashAlgorithmName.SHA1); -#else - using var gen = new Rfc2898DeriveBytes(password, salt, 1000); -#endif using var tdes = TripleDES.Create(); - tdes.Mode = CipherMode.CBC; tdes.Padding = PaddingMode.PKCS7; + +#if NET10_0_OR_GREATER + tdes.Key = Rfc2898DeriveBytes.Pbkdf2(password, salt, 1000, HashAlgorithmName.SHA1, tdes.KeySize / 8); + tdes.IV = Rfc2898DeriveBytes.Pbkdf2(password, salt, 1000, HashAlgorithmName.SHA1, tdes.BlockSize / 8); +#elif NET8_0_OR_GREATER + using var gen = new Rfc2898DeriveBytes(password, salt, 1000, HashAlgorithmName.SHA1); tdes.Key = gen.GetBytes(tdes.KeySize / 8); tdes.IV = gen.GetBytes(tdes.BlockSize / 8); +#else + using var gen = new Rfc2898DeriveBytes(password, salt, 1000); + tdes.Key = gen.GetBytes(tdes.KeySize / 8); + tdes.IV = gen.GetBytes(tdes.BlockSize / 8); +#endif using var ms = new MemoryStream(); using var cs = new CryptoStream(ms, tdes.CreateEncryptor(), CryptoStreamMode.Write); @@ -361,7 +380,6 @@ namespace System.Security.Cryptography #endregion Triple DES -#pragma warning restore SYSLIB0041 #endregion Encryption #region Hashing diff --git a/test/AMWD.Common.Tests/Utilities/CryptographyHelperTest.cs b/test/AMWD.Common.Tests/Utilities/CryptographyHelperTest.cs index 8d027a0..fd400f7 100644 --- a/test/AMWD.Common.Tests/Utilities/CryptographyHelperTest.cs +++ b/test/AMWD.Common.Tests/Utilities/CryptographyHelperTest.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using System.IO; +using System.Linq; using System.Security.Cryptography; using System.Text.RegularExpressions; using AMWD.Common.Tests.Utils; @@ -33,7 +34,7 @@ namespace UnitTests.Common.Utilities #region AES [TestMethod] - public void ShouldEncryptAesWithoutSalt() // required to test the encryption itself + public void ShouldEncryptAesWithoutSalt() { // arrange using var _ = CryptographyHelperSaltMock.Create(0); @@ -43,7 +44,7 @@ namespace UnitTests.Common.Utilities string password1 = "P@ssw0rd!"; string password2 = "P@ssw0rd"; - byte[] expectedBytes = [0x7c, 0x7b, 0x77, 0x56, 0x91, 0x1a, 0xd9, 0xc0, 0x72, 0x70, 0x36, 0x88, 0x9f, 0xb4, 0xb5, 0xbc]; + byte[] expectedBytes = [0xda, 0xc2, 0x74, 0x2c, 0x74, 0x50, 0x8b, 0xac, 0x6c, 0xbe, 0x60, 0x8c, 0x62, 0x32, 0xc2, 0xdd]; // act byte[] cipherBytes1 = CryptographyHelper.AesEncrypt(bytes, password1); @@ -53,10 +54,10 @@ namespace UnitTests.Common.Utilities // assert CollectionAssert.AreEqual(expectedBytes, cipherBytes1); - Assert.AreEqual("ueLuhFNpCuYmx8v3hczHtg==", cipherStr1); + Assert.AreEqual("R/Bgu4VSk9EzvXRduyn02w==", cipherStr1); CollectionAssert.AreNotEqual(expectedBytes, cipherBytes2); - Assert.AreNotEqual("ueLuhFNpCuYmx8v3hczHtg==", cipherStr2); + Assert.AreNotEqual("R/Bgu4VSk9EzvXRduyn02w==", cipherStr2); } [TestMethod] @@ -65,8 +66,8 @@ namespace UnitTests.Common.Utilities // arrange using var _ = CryptographyHelperSaltMock.Create(0); - string cipherStr = "ueLuhFNpCuYmx8v3hczHtg=="; - byte[] cipherBytes = [0x7c, 0x7b, 0x77, 0x56, 0x91, 0x1a, 0xd9, 0xc0, 0x72, 0x70, 0x36, 0x88, 0x9f, 0xb4, 0xb5, 0xbc]; + string cipherStr = "R/Bgu4VSk9EzvXRduyn02w=="; + byte[] cipherBytes = [0xda, 0xc2, 0x74, 0x2c, 0x74, 0x50, 0x8b, 0xac, 0x6c, 0xbe, 0x60, 0x8c, 0x62, 0x32, 0xc2, 0xdd]; string password1 = "P@ssw0rd!"; string password2 = "P@ssw0rd"; @@ -147,7 +148,7 @@ namespace UnitTests.Common.Utilities #region TripleDES [TestMethod] - public void ShouldEncryptTdesWithoutSalt() // required to test the encryption itself + public void ShouldEncryptTdesWithoutSalt() { // arrange using var _ = CryptographyHelperSaltMock.Create(0); @@ -157,7 +158,7 @@ namespace UnitTests.Common.Utilities string password1 = "P@ssw0rd!"; string password2 = "P@ssw0rd"; - byte[] expectedBytes = [0xbf, 0x59, 0x1f, 0x48, 0x69, 0xab, 0x18, 0xc7]; + byte[] expectedBytes = [0xcf, 0x1a, 0x60, 0x41, 0xbb, 0x69, 0x50, 0x24]; // act byte[] cipherBytes1 = CryptographyHelper.TripleDesEncrypt(bytes, password1); @@ -167,10 +168,10 @@ namespace UnitTests.Common.Utilities // assert CollectionAssert.AreEqual(expectedBytes, cipherBytes1); - Assert.AreEqual("1l74soBuuEI=", cipherStr1); + Assert.AreEqual("EB2GFc/pIUE=", cipherStr1); CollectionAssert.AreNotEqual(expectedBytes, cipherBytes2); - Assert.AreNotEqual("1l74soBuuEI=", cipherStr2); + Assert.AreNotEqual("EB2GFc/pIUE=", cipherStr2); } [TestMethod] @@ -179,8 +180,8 @@ namespace UnitTests.Common.Utilities // arrange using var _ = CryptographyHelperSaltMock.Create(0); - string cipherStr = "1l74soBuuEI="; - byte[] cipherBytes = [0xbf, 0x59, 0x1f, 0x48, 0x69, 0xab, 0x18, 0xc7]; + string cipherStr = "EB2GFc/pIUE="; + byte[] cipherBytes = [0xcf, 0x1a, 0x60, 0x41, 0xbb, 0x69, 0x50, 0x24]; string password1 = "P@ssw0rd!"; string password2 = "P@ssw0rd";