From dcc8875661cfaf8e5c4bd48b120166d6c585b51b Mon Sep 17 00:00:00 2001 From: Ogoun Date: Sun, 14 May 2023 17:06:00 +0300 Subject: [PATCH] Fix config, append TokenEncryptor --- TestApp/Program.cs | 13 ++- ZeroLevel.UnitTests/TokenEncryptorTest.cs | 68 +++++++++++++ .../Services/Config/BaseConfiguration.cs | 4 +- ZeroLevel/Services/Config/Configuration.cs | 2 - .../Services/Shedulling/ExpiredObject.cs | 2 +- ZeroLevel/Services/TokenEncryptor.cs | 97 +++++++++++++++++++ ZeroLevel/ZeroLevel.csproj | 8 +- 7 files changed, 182 insertions(+), 12 deletions(-) create mode 100644 ZeroLevel.UnitTests/TokenEncryptorTest.cs create mode 100644 ZeroLevel/Services/TokenEncryptor.cs diff --git a/TestApp/Program.cs b/TestApp/Program.cs index c3d4b86..243d099 100644 --- a/TestApp/Program.cs +++ b/TestApp/Program.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Concurrent; -using ZeroLevel.Services.Network.Utils; namespace TestApp { @@ -8,7 +6,16 @@ namespace TestApp { private static void Main(string[] args) { - Console.WriteLine(Network.ExternalIP); + AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; + } + + private static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs e) + { + if (e.Name.StartsWith("Microsoft.Build.")) + { + // искать в локальной папке + } + return null; } } } \ No newline at end of file diff --git a/ZeroLevel.UnitTests/TokenEncryptorTest.cs b/ZeroLevel.UnitTests/TokenEncryptorTest.cs new file mode 100644 index 0000000..15ef310 --- /dev/null +++ b/ZeroLevel.UnitTests/TokenEncryptorTest.cs @@ -0,0 +1,68 @@ +using System; +using Xunit; +using ZeroLevel.Services; +using ZeroLevel.Services.Serialization; + +namespace ZeroLevel.UnitTests +{ + public class TokenEncryptorTest + { + public class TestClaims + : IBinarySerializable, IEquatable + { + public string Login; + public string Name; + + public void Deserialize(IBinaryReader reader) + { + this.Login = reader.ReadString(); + this.Name = reader.ReadString(); + } + + public override bool Equals(object obj) + { + return this.Equals(obj as TestClaims); + } + + public bool Equals(TestClaims other) + { + if (other == null) return false; + if (string.Compare(this.Login, other.Login, StringComparison.OrdinalIgnoreCase) != 0) return false; + if (string.Compare(this.Name, other.Name, StringComparison.OrdinalIgnoreCase) != 0) return false; + return true; + } + + public void Serialize(IBinaryWriter writer) + { + writer.WriteString(this.Login); + writer.WriteString(this.Name); + } + } + + [Fact] + public void TokenEncryptorEncryptDecryptTest() + { + // Arrange + var a1 = new TestClaims { Login = null, Name = "name" }; + var a2 = new TestClaims { Login = "login", Name = "name" }; + var a3 = new TestClaims { Login = null, Name = null }; + var key = "testkey"; + var salt = "testsalt"; + var tokenEncryptor = new TokenEncryptor(key, salt); + + // Act + var a1_token = tokenEncryptor.WriteToToken(a1); + var a2_token = tokenEncryptor.WriteToToken(a2); + var a3_token = tokenEncryptor.WriteToToken(a3); + + var a1_decrypted = tokenEncryptor.ReadFromToken(a1_token); + var a2_decrypted = tokenEncryptor.ReadFromToken(a2_token); + var a3_decrypted = tokenEncryptor.ReadFromToken(a3_token); + + // Assert + Assert.True(a1.Equals(a1_decrypted)); + Assert.True(a2.Equals(a2_decrypted)); + Assert.True(a3.Equals(a3_decrypted)); + } + } +} diff --git a/ZeroLevel/Services/Config/BaseConfiguration.cs b/ZeroLevel/Services/Config/BaseConfiguration.cs index 07bd9fb..ebf2541 100644 --- a/ZeroLevel/Services/Config/BaseConfiguration.cs +++ b/ZeroLevel/Services/Config/BaseConfiguration.cs @@ -527,8 +527,8 @@ namespace ZeroLevel.Services.Config else { var elements = values.Select(v => parser.Parse(v)).ToArray(); - var arrayBuilder = CollectionFactory.CreateArray(itemType, elements.Length); - foreach (var item in elements) + var arrayBuilder = CollectionFactory.CreateArray(itemType, (elements[0] as Array).Length); + foreach (var item in (elements[0] as Array)) { arrayBuilder.Set(item, index); index++; diff --git a/ZeroLevel/Services/Config/Configuration.cs b/ZeroLevel/Services/Config/Configuration.cs index 5b221ea..9f5ad5f 100644 --- a/ZeroLevel/Services/Config/Configuration.cs +++ b/ZeroLevel/Services/Config/Configuration.cs @@ -401,8 +401,6 @@ namespace ZeroLevel } #endregion Read configuration - - public static IConfiguration Merge(ConfigurationRecordExistBehavior existRecordBehavior, params IConfiguration[] configurations) { var result = Configuration.Create(); diff --git a/ZeroLevel/Services/Shedulling/ExpiredObject.cs b/ZeroLevel/Services/Shedulling/ExpiredObject.cs index 76214e5..b1533c3 100644 --- a/ZeroLevel/Services/Shedulling/ExpiredObject.cs +++ b/ZeroLevel/Services/Shedulling/ExpiredObject.cs @@ -6,7 +6,7 @@ namespace ZeroLevel.Services.Shedulling /// /// A wrapper around an Action that stores the time at which an action should be performed, as well as a link to the next action. /// - internal class ExpiredObject + internal sealed class ExpiredObject { private static long _counter = 0; diff --git a/ZeroLevel/Services/TokenEncryptor.cs b/ZeroLevel/Services/TokenEncryptor.cs new file mode 100644 index 0000000..51f3af1 --- /dev/null +++ b/ZeroLevel/Services/TokenEncryptor.cs @@ -0,0 +1,97 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using ZeroLevel.Services.Serialization; + +namespace ZeroLevel.Services +{ + public class TokenEncryptor + { + private sealed class Cryptor + { + private const int Rfc2898KeygenIterations = 100; + private const int AesKeySizeInBits = 128; + private readonly byte[] _password; + private readonly byte[] _salt; + public Cryptor(string pwd, string salt) + { + _password = Encoding.ASCII.GetBytes(pwd); + _salt = Encoding.ASCII.GetBytes(salt); + } + + public byte[] Encrypt(byte[] data) + { + using (Aes aes = new AesManaged()) + { + aes.Padding = PaddingMode.PKCS7; + aes.KeySize = AesKeySizeInBits; + int KeyStrengthInBytes = aes.KeySize / 8; + System.Security.Cryptography.Rfc2898DeriveBytes rfc2898 = + new System.Security.Cryptography.Rfc2898DeriveBytes(_password, _salt, Rfc2898KeygenIterations); + aes.Key = rfc2898.GetBytes(KeyStrengthInBytes); + aes.IV = rfc2898.GetBytes(KeyStrengthInBytes); + using (MemoryStream ms = new MemoryStream()) + { + using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write)) + { + cs.Write(data, 0, data.Length); + } + return ms.ToArray(); + } + } + } + + public byte[] Decrypt(byte[] data) + { + using (Aes aes = new AesManaged()) + { + aes.Padding = PaddingMode.PKCS7; + aes.KeySize = AesKeySizeInBits; + int KeyStrengthInBytes = aes.KeySize / 8; + System.Security.Cryptography.Rfc2898DeriveBytes rfc2898 = + new System.Security.Cryptography.Rfc2898DeriveBytes(_password, _salt, Rfc2898KeygenIterations); + aes.Key = rfc2898.GetBytes(KeyStrengthInBytes); + aes.IV = rfc2898.GetBytes(KeyStrengthInBytes); + + using (MemoryStream ms = new MemoryStream()) + { + using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write)) + { + cs.Write(data, 0, data.Length); + } + return ms.ToArray(); + } + } + } + } + + private Cryptor _cryptor; + public TokenEncryptor(string key, string salt) + { + _cryptor = new Cryptor(key, salt); + } + + public T ReadFromToken(string token) + where T : IBinarySerializable + { + if (string.IsNullOrWhiteSpace(token) == false && string.CompareOrdinal(token, "null") != 0) + { + var data = Convert.FromBase64String(token); + var decryptedBytes = _cryptor.Decrypt(data); + var decryptedValue = MessageSerializer.Deserialize(decryptedBytes); + return decryptedValue; + } + return default!; + } + + public string WriteToToken(T value) + where T : IBinarySerializable + { + var decryptedBytes = MessageSerializer.Serialize(value); + var encryptedBytes = _cryptor.Encrypt(decryptedBytes); + var token = Convert.ToBase64String(encryptedBytes); + return token; + } + } +} diff --git a/ZeroLevel/ZeroLevel.csproj b/ZeroLevel/ZeroLevel.csproj index 8ffc66d..dc05807 100644 --- a/ZeroLevel/ZeroLevel.csproj +++ b/ZeroLevel/ZeroLevel.csproj @@ -6,16 +6,16 @@ ogoun ogoun - 3.3.9.8 - Getting the end date of the task in the sheduler + 3.3.9.9 + Token encryptor https://github.com/ogoun/Zero/wiki Copyright Ogoun 2023 https://github.com/ogoun/Zero git - 3.3.9.8 - 3.3.9.8 + 3.3.9.9 + 3.3.9.9 AnyCPU;x64;x86 zero.png full