bunch of fixes
This commit is contained in:
@@ -0,0 +1,28 @@
|
|||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
|
public class AesDecryptor :
|
||||||
|
IDecryptor
|
||||||
|
{
|
||||||
|
private const int IvSize = 16;
|
||||||
|
|
||||||
|
public byte[] Decrypt(byte[] cipher, byte[] key)
|
||||||
|
{
|
||||||
|
Span<byte> iv = cipher.AsSpan(0, IvSize);
|
||||||
|
ReadOnlySpan<byte> encryptedContent = cipher.AsSpan(IvSize);
|
||||||
|
|
||||||
|
using Aes aes = Aes.Create();
|
||||||
|
aes.Key = key;
|
||||||
|
aes.IV = iv.ToArray();
|
||||||
|
|
||||||
|
using MemoryStream memoryStream = new(encryptedContent.ToArray());
|
||||||
|
using ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
|
||||||
|
using CryptoStream cryptoStream = new(memoryStream, decryptor, CryptoStreamMode.Read);
|
||||||
|
|
||||||
|
using MemoryStream resultStream = new();
|
||||||
|
cryptoStream.CopyTo(resultStream);
|
||||||
|
|
||||||
|
return resultStream.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
|
public class AesEncryptor :
|
||||||
|
IEncryptor
|
||||||
|
{
|
||||||
|
private const int IvSize = 16;
|
||||||
|
|
||||||
|
public byte[] Encrypt(byte[] data,
|
||||||
|
byte[] key)
|
||||||
|
{
|
||||||
|
if (key.Length != 32)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Key must be 256 bits (32 bytes).");
|
||||||
|
}
|
||||||
|
|
||||||
|
using Aes aes = Aes.Create();
|
||||||
|
aes.Key = key;
|
||||||
|
aes.GenerateIV();
|
||||||
|
|
||||||
|
using MemoryStream memoryStream = new();
|
||||||
|
memoryStream.Write(aes.IV.AsSpan(0, IvSize));
|
||||||
|
|
||||||
|
using (ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV))
|
||||||
|
using (CryptoStream cryptoStream = new(memoryStream, encryptor, CryptoStreamMode.Write))
|
||||||
|
{
|
||||||
|
cryptoStream.Write(data, 0, data.Length);
|
||||||
|
cryptoStream.FlushFinalBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
return memoryStream.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -120,7 +120,6 @@ public class ConfigurationSource<TConfiguration>(IConfigurationFile<TConfigurati
|
|||||||
lock (lockingObject)
|
lock (lockingObject)
|
||||||
{
|
{
|
||||||
IFileInfo fileInfo = configurationFile.FileInfo;
|
IFileInfo fileInfo = configurationFile.FileInfo;
|
||||||
|
|
||||||
if (File.Exists(fileInfo.PhysicalPath))
|
if (File.Exists(fileInfo.PhysicalPath))
|
||||||
{
|
{
|
||||||
static Stream OpenRead(IFileInfo fileInfo)
|
static Stream OpenRead(IFileInfo fileInfo)
|
||||||
@@ -153,11 +152,14 @@ public class ConfigurationSource<TConfiguration>(IConfigurationFile<TConfigurati
|
|||||||
|
|
||||||
if (currentNode is not null)
|
if (currentNode is not null)
|
||||||
{
|
{
|
||||||
value = JsonSerializer.Deserialize<TConfiguration>(currentNode[segments[lastIndex]],
|
if (currentNode[segments[lastIndex]] is JsonNode sectionNode)
|
||||||
|
{
|
||||||
|
value = JsonSerializer.Deserialize<TConfiguration>(sectionNode,
|
||||||
serializerOptions ?? defaultSerializerOptions());
|
serializerOptions ?? defaultSerializerOptions());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
value = default;
|
value = default;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1,21 +1,24 @@
|
|||||||
namespace Toolkit.Foundation;
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
public class ConfigurationWriter<TConfiguration>(IConfigurationSource<TConfiguration> source) :
|
public class ConfigurationWriter<TConfiguration>(IConfigurationSource<TConfiguration> source,
|
||||||
|
IConfigurationFactory<TConfiguration> factory) :
|
||||||
IConfigurationWriter<TConfiguration>
|
IConfigurationWriter<TConfiguration>
|
||||||
where TConfiguration :
|
where TConfiguration :
|
||||||
class
|
class
|
||||||
{
|
{
|
||||||
public void Write(Action<TConfiguration> updateDelegate)
|
public void Write(Action<TConfiguration> updateDelegate)
|
||||||
{
|
{
|
||||||
if (source.TryGet(out TConfiguration? value))
|
if (!source.TryGet(out TConfiguration? value))
|
||||||
{
|
{
|
||||||
|
value = (TConfiguration)factory.Create();
|
||||||
|
}
|
||||||
|
|
||||||
if (value is not null)
|
if (value is not null)
|
||||||
{
|
{
|
||||||
updateDelegate?.Invoke(value);
|
updateDelegate?.Invoke(value);
|
||||||
Write(value);
|
Write(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void Write(object value) => source.Set(value);
|
public void Write(object value) => source.Set(value);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
|
public class Container<T> :
|
||||||
|
IContainer<T>
|
||||||
|
{
|
||||||
|
public T? Value { get; private set; }
|
||||||
|
|
||||||
|
public void Set(T value) => Value = value;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
|
public interface IContainer<T>
|
||||||
|
{
|
||||||
|
T? Value { get; }
|
||||||
|
|
||||||
|
void Set(T value);
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Toolkit.Foundation;
|
||||||
|
public interface IDecryptor
|
||||||
|
{
|
||||||
|
byte[] Decrypt(byte[] cipher,
|
||||||
|
byte[] key);
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
namespace Toolkit.Foundation;
|
||||||
|
public interface IEncryptor
|
||||||
|
{
|
||||||
|
byte[] Encrypt(byte[] data, byte[] key);
|
||||||
|
}
|
||||||
@@ -100,7 +100,7 @@ public static class IHostBuilderExtension
|
|||||||
return new ConfigurationFile<TConfiguration>(fileInfo);
|
return new ConfigurationFile<TConfiguration>(fileInfo);
|
||||||
});
|
});
|
||||||
|
|
||||||
services.TryAddKeyedSingleton<IConfigurationSource<TConfiguration>>(section, (provider, KeyAccelerator) =>
|
services.TryAddKeyedTransient<IConfigurationSource<TConfiguration>>(section, (provider, key) =>
|
||||||
{
|
{
|
||||||
JsonSerializerOptions? defaultSerializer = null;
|
JsonSerializerOptions? defaultSerializer = null;
|
||||||
if (serializerDelegate is not null)
|
if (serializerDelegate is not null)
|
||||||
@@ -119,10 +119,11 @@ public static class IHostBuilderExtension
|
|||||||
provider.GetRequiredKeyedService<IConfigurationFactory<TConfiguration>>(key)));
|
provider.GetRequiredKeyedService<IConfigurationFactory<TConfiguration>>(key)));
|
||||||
|
|
||||||
services.TryAddKeyedTransient<IConfigurationWriter<TConfiguration>>(section, (provider, key) =>
|
services.TryAddKeyedTransient<IConfigurationWriter<TConfiguration>>(section, (provider, key) =>
|
||||||
new ConfigurationWriter<TConfiguration>(provider.GetRequiredKeyedService<IConfigurationSource<TConfiguration>>(key)));
|
new ConfigurationWriter<TConfiguration>(provider.GetRequiredKeyedService<IConfigurationSource<TConfiguration>>(key),
|
||||||
|
provider.GetRequiredKeyedService<IConfigurationFactory<TConfiguration>>(key)));
|
||||||
|
|
||||||
services.TryAddKeyedTransient<IConfigurationFactory<TConfiguration>>(section, (provider, key) =>
|
services.TryAddKeyedTransient<IConfigurationFactory<TConfiguration>>(section, (provider, key) =>
|
||||||
new ConfigurationFactory<TConfiguration>(() => defaultConfiguration ?? new TConfiguration()));
|
new ConfigurationFactory<TConfiguration>(() => defaultConfiguration ?? provider.GetRequiredKeyedService<TConfiguration>(key)));
|
||||||
|
|
||||||
services.AddTransient<IInitializer, ConfigurationInitializer<TConfiguration>>(provider =>
|
services.AddTransient<IInitializer, ConfigurationInitializer<TConfiguration>>(provider =>
|
||||||
new ConfigurationInitializer<TConfiguration>(provider.GetRequiredKeyedService<IConfigurationReader<TConfiguration>>(section),
|
new ConfigurationInitializer<TConfiguration>(provider.GetRequiredKeyedService<IConfigurationReader<TConfiguration>>(section),
|
||||||
@@ -136,6 +137,9 @@ public static class IHostBuilderExtension
|
|||||||
services.TryAddKeyedTransient<IWritableConfiguration<TConfiguration>>(section, (provider, key) =>
|
services.TryAddKeyedTransient<IWritableConfiguration<TConfiguration>>(section, (provider, key) =>
|
||||||
new WritableConfiguration<TConfiguration>(provider.GetRequiredKeyedService<IConfigurationWriter<TConfiguration>>(key)));
|
new WritableConfiguration<TConfiguration>(provider.GetRequiredKeyedService<IConfigurationWriter<TConfiguration>>(key)));
|
||||||
|
|
||||||
|
services.TryAddTransient<IWritableConfiguration<TConfiguration>>(provider =>
|
||||||
|
new WritableConfiguration<TConfiguration>(provider.GetRequiredKeyedService<IConfigurationWriter<TConfiguration>>(section)));
|
||||||
|
|
||||||
services.TryAddKeyedTransient<IConfigurationDescriptor<TConfiguration>>(section, (provider, key) =>
|
services.TryAddKeyedTransient<IConfigurationDescriptor<TConfiguration>>(section, (provider, key) =>
|
||||||
new ConfigurationDescriptor<TConfiguration>(section, provider.GetRequiredKeyedService<IConfigurationReader<TConfiguration>>(key)));
|
new ConfigurationDescriptor<TConfiguration>(section, provider.GetRequiredKeyedService<IConfigurationReader<TConfiguration>>(key)));
|
||||||
|
|
||||||
|
|||||||
@@ -4,3 +4,8 @@ public interface IInitializer
|
|||||||
{
|
{
|
||||||
Task Initialize();
|
Task Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface IInitializer<T>
|
||||||
|
{
|
||||||
|
Task<T> Initialize();
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
namespace Toolkit.Foundation;
|
||||||
|
public interface IKeyDeriver
|
||||||
|
{
|
||||||
|
byte[] DeriveKey(string password, byte[] salt, int keySize = 32, int iterations = 10000);
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
namespace Toolkit.Foundation;
|
||||||
|
public interface IKeyGenerator
|
||||||
|
{
|
||||||
|
byte[] Generate(int size);
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
namespace Toolkit.Foundation;
|
||||||
|
public interface IPasswordHasher
|
||||||
|
{
|
||||||
|
string HashPassword(string password, int iterations = 10000);
|
||||||
|
}
|
||||||
@@ -35,126 +35,6 @@ public static class IServiceCollectionExtensions
|
|||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IServiceCollection AddConfiguration<TConfiguration,
|
|
||||||
TValue>(this IServiceCollection services,
|
|
||||||
Func<TConfiguration, Action<TValue>> changed)
|
|
||||||
where TConfiguration : class
|
|
||||||
where TValue : class, new()
|
|
||||||
{
|
|
||||||
services.AddSingleton(new ConfigurationValue<TConfiguration, TValue>(changed));
|
|
||||||
services.AddHandler<ConfigurationChangedHandler<TConfiguration, TValue>>();
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IServiceCollection AddConfiguration<TConfiguration>(this IServiceCollection services,
|
|
||||||
string section)
|
|
||||||
where TConfiguration : class, new() =>
|
|
||||||
services.AddConfiguration<TConfiguration>(section, "Settings.json", null);
|
|
||||||
|
|
||||||
public static IServiceCollection AddConfiguration<TConfiguration>(this IServiceCollection services)
|
|
||||||
where TConfiguration : class, new() =>
|
|
||||||
services.AddConfiguration<TConfiguration>(typeof(TConfiguration).Name, "Settings.json", null);
|
|
||||||
|
|
||||||
public static IServiceCollection AddConfiguration<TConfiguration>(this IServiceCollection services,
|
|
||||||
Action<TConfiguration> configurationDelegate)
|
|
||||||
where TConfiguration : class, new()
|
|
||||||
{
|
|
||||||
TConfiguration configuration = new();
|
|
||||||
configurationDelegate.Invoke(configuration);
|
|
||||||
|
|
||||||
return services.AddConfiguration(typeof(TConfiguration).Name, "Settings.json", configuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IServiceCollection AddConfiguration<TConfiguration>(this IServiceCollection services,
|
|
||||||
Action<TConfiguration> configurationDelegate,
|
|
||||||
string section)
|
|
||||||
where TConfiguration : class, new()
|
|
||||||
{
|
|
||||||
TConfiguration configuration = new();
|
|
||||||
configurationDelegate.Invoke(configuration);
|
|
||||||
|
|
||||||
return services.AddConfiguration(section, "Settings.json", configuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IServiceCollection AddConfiguration<TConfiguration>(this IServiceCollection services,
|
|
||||||
TConfiguration configuration)
|
|
||||||
where TConfiguration : class, new() =>
|
|
||||||
services.AddConfiguration(configuration.GetType().Name, "Settings.json", configuration);
|
|
||||||
|
|
||||||
public static IServiceCollection AddConfiguration<TConfiguration>(this IServiceCollection services,
|
|
||||||
object configuration)
|
|
||||||
where TConfiguration : class, new() =>
|
|
||||||
services.AddConfiguration(configuration.GetType().Name,
|
|
||||||
"Settings.json", (TConfiguration?)configuration);
|
|
||||||
|
|
||||||
public static IServiceCollection AddConfiguration<TConfiguration>(this IServiceCollection services,
|
|
||||||
string section,
|
|
||||||
string path = "Settings.json",
|
|
||||||
TConfiguration? defaultConfiguration = null,
|
|
||||||
Action<JsonSerializerOptions>? serializerDelegate = null)
|
|
||||||
where TConfiguration : class, new()
|
|
||||||
{
|
|
||||||
services.TryAddSingleton<IConfigurationFile<TConfiguration>>(provider =>
|
|
||||||
{
|
|
||||||
IFileInfo? fileInfo = null;
|
|
||||||
if (provider.GetService<IHostEnvironment>() is IHostEnvironment hostEnvironment)
|
|
||||||
{
|
|
||||||
IFileProvider fileProvider = hostEnvironment.ContentRootFileProvider;
|
|
||||||
fileInfo = fileProvider.GetFileInfo(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
fileInfo ??= new PhysicalFileInfo(new FileInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path)));
|
|
||||||
return new ConfigurationFile<TConfiguration>(fileInfo);
|
|
||||||
});
|
|
||||||
|
|
||||||
services.TryAddKeyedSingleton<IConfigurationSource<TConfiguration>>(section, (provider, KeyAccelerator) =>
|
|
||||||
{
|
|
||||||
JsonSerializerOptions? defaultSerializer = null;
|
|
||||||
if (serializerDelegate is not null)
|
|
||||||
{
|
|
||||||
defaultSerializer = new JsonSerializerOptions();
|
|
||||||
serializerDelegate.Invoke(defaultSerializer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ConfigurationSource<TConfiguration>(provider.GetRequiredService<IConfigurationFile<TConfiguration>>(),
|
|
||||||
section, defaultSerializer);
|
|
||||||
});
|
|
||||||
|
|
||||||
//services.AddHostedService<ConfigurationMonitor<TConfiguration>>();
|
|
||||||
services.TryAddKeyedTransient<IConfigurationReader<TConfiguration>>(section, (provider, key) =>
|
|
||||||
new ConfigurationReader<TConfiguration>(provider.GetRequiredKeyedService<IConfigurationSource<TConfiguration>>(key),
|
|
||||||
provider.GetRequiredKeyedService<IConfigurationFactory<TConfiguration>>(key)));
|
|
||||||
|
|
||||||
services.TryAddKeyedTransient<IConfigurationWriter<TConfiguration>>(section, (provider, key) =>
|
|
||||||
new ConfigurationWriter<TConfiguration>(provider.GetRequiredKeyedService<IConfigurationSource<TConfiguration>>(key)));
|
|
||||||
|
|
||||||
services.TryAddKeyedTransient<IConfigurationFactory<TConfiguration>>(section, (provider, key) =>
|
|
||||||
new ConfigurationFactory<TConfiguration>(() => defaultConfiguration ?? new TConfiguration()));
|
|
||||||
|
|
||||||
services.AddTransient<IInitializer, ConfigurationInitializer<TConfiguration>>(provider =>
|
|
||||||
new ConfigurationInitializer<TConfiguration>(provider.GetRequiredKeyedService<IConfigurationReader<TConfiguration>>(section),
|
|
||||||
provider.GetRequiredKeyedService<IConfigurationWriter<TConfiguration>>(section),
|
|
||||||
provider.GetRequiredKeyedService<IConfigurationFactory<TConfiguration>>(section),
|
|
||||||
provider.GetRequiredService<IPublisher>()));
|
|
||||||
|
|
||||||
services.AddTransient<IConfigurationInitializer<TConfiguration>, ConfigurationInitializer<TConfiguration>>(provider =>
|
|
||||||
provider.GetRequiredService<IServiceFactory>().Create<ConfigurationInitializer<TConfiguration>>(section));
|
|
||||||
|
|
||||||
services.AddTransient<IWritableConfiguration<TConfiguration>, WritableConfiguration<TConfiguration>>();
|
|
||||||
|
|
||||||
services.TryAddKeyedTransient<IConfigurationDescriptor<TConfiguration>>(section, (provider, key) =>
|
|
||||||
new ConfigurationDescriptor<TConfiguration>(section, provider.GetRequiredKeyedService<IConfigurationReader<TConfiguration>>(key)));
|
|
||||||
|
|
||||||
services.AddTransient(provider =>
|
|
||||||
provider.GetRequiredKeyedService<IConfigurationDescriptor<TConfiguration>>(section));
|
|
||||||
|
|
||||||
services.AddTransient(provider =>
|
|
||||||
provider.GetRequiredKeyedService<IConfigurationDescriptor<TConfiguration>>(section).Value);
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IServiceCollection AddHandler<THandler>(this IServiceCollection services,
|
public static IServiceCollection AddHandler<THandler>(this IServiceCollection services,
|
||||||
ServiceLifetime lifetime = ServiceLifetime.Transient)
|
ServiceLifetime lifetime = ServiceLifetime.Transient)
|
||||||
where THandler : IHandler
|
where THandler : IHandler
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
|
public class KeyDeriver :
|
||||||
|
IKeyDeriver
|
||||||
|
{
|
||||||
|
public byte[] DeriveKey(string password, byte[] salt, int keySize = 32, int iterations = 100000)
|
||||||
|
{
|
||||||
|
using Rfc2898DeriveBytes pbkdf2 = new(password, salt, iterations, HashAlgorithmName.SHA256);
|
||||||
|
return pbkdf2.GetBytes(keySize);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
|
public class KeyGenerator :
|
||||||
|
IKeyGenerator
|
||||||
|
{
|
||||||
|
public byte[] Generate(int size)
|
||||||
|
{
|
||||||
|
byte[] key = new byte[size];
|
||||||
|
RandomNumberGenerator.Fill(key);
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
|
public class PasswordHasher :
|
||||||
|
IPasswordHasher
|
||||||
|
{
|
||||||
|
private const int SaltSize = 16;
|
||||||
|
|
||||||
|
public string HashPassword(string password, int iterations = 10000)
|
||||||
|
{
|
||||||
|
using Rfc2898DeriveBytes pbkdf2 = new(password, SaltSize, iterations, HashAlgorithmName.SHA256);
|
||||||
|
|
||||||
|
byte[] salt = pbkdf2.Salt;
|
||||||
|
byte[] hash = pbkdf2.GetBytes(32);
|
||||||
|
|
||||||
|
return $"{Convert.ToBase64String(salt)}:{Convert.ToBase64String(hash)}";
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user