feat: Implementieren der Verschlüsselungs- und Entschlüsselungsdienste mit AES und Integration in die API

- Hinzufügen der `Encryptor`-Klasse für AES-Verschlüsselung und -Entschlüsselung.
- Implementierung des `EncryptionController` zur Bereitstellung von Endpunkten für Verschlüsselung, Entschlüsselung und Generierung von Verschlüsselungsparametern.
- Erweiterung der DI-Konfiguration mit `AddEncryptor`-Erweiterungsmethode und Integration in `Program.cs`.
- Bedingte Registrierung des `EncryptionController` basierend auf der Konfiguration `UseEncryptor`, um sicherzustellen, dass der Controller nur bei Bedarf verfügbar ist.
- Implementierung von Lazy Loading für die Verbindungszeichenfolge in `UserManagerDbContext` zur sicheren Handhabung von verschlüsselten Verbindungszeichenfolgen.
This commit is contained in:
Developer 02
2024-08-29 11:35:47 +02:00
parent c8bcb5a6ac
commit 6e973a494e
8 changed files with 179 additions and 12 deletions

View File

@@ -1,9 +1,11 @@
using DigitalData.UserManager.Application.Contracts;
using DigitalData.UserManager.Application.MappingProfiles;
using DigitalData.UserManager.Application.Services;
using DigitalData.UserManager.Application.Services.Options;
using DigitalData.UserManager.Infrastructure.Contracts;
using DigitalData.UserManager.Infrastructure.Repositories;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace DigitalData.UserManager.Application
@@ -40,5 +42,12 @@ namespace DigitalData.UserManager.Application
.AddScoped<IModuleService, ModuleService>()
.AddScoped<IModuleOfUserService, ModuleOfUserService>()
.AddScoped<IUserRepService, UserRepService>();
public static IServiceCollection AddEncryptor(this IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton<Encryptor>();
services.Configure<EncryptionParameters>(configuration);
return services;
}
}
}

View File

@@ -28,6 +28,7 @@
<PackageReference Include="DigitalData.Core.Application" Version="1.0.0" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher.Abstraction" Version="1.0.0" />
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="7.0.16" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="7.0.0" />
<PackageReference Include="System.DirectoryServices" Version="7.0.1" />
<PackageReference Include="System.DirectoryServices.AccountManagement" Version="7.0.1" />
<PackageReference Include="System.DirectoryServices.Protocols" Version="7.0.1" />

View File

@@ -0,0 +1,78 @@
using DigitalData.UserManager.Application.Services.Options;
using Microsoft.Extensions.Options;
using System.Security.Cryptography;
using System.Text;
namespace DigitalData.UserManager.Application.Services
{
public class Encryptor
{
public const int KeyByteLength = 32;
private readonly EncryptionParameters _params;
public Encryptor(IOptions<EncryptionParameters> options)
{
_params = options.Value;
}
public string Encrypt(string plainText) => Encrypt(plainText, _params.Key, _params.IV);
public string Decrypt(string cipherText) => Decrypt(cipherText, _params.Key, _params.IV);
public static string Encrypt(string plainText, string key, string iv)
{
using Aes aes = Aes.Create();
aes.KeySize = KeyByteLength * 8;
aes.Key = AdjustKeySize(Encoding.UTF8.GetBytes(key), aes.KeySize / 8);
aes.IV = AdjustKeySize(Encoding.UTF8.GetBytes(iv), aes.BlockSize / 8);
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
using MemoryStream ms = new();
using (CryptoStream cs = new(ms, encryptor, CryptoStreamMode.Write))
{
using StreamWriter sw = new(cs);
sw.Write(plainText);
}
return Convert.ToBase64String(ms.ToArray());
}
public static string Decrypt(string cipherText, string key, string iv)
{
using Aes aes = Aes.Create();
aes.KeySize = KeyByteLength * 8;
aes.Key = AdjustKeySize(Encoding.UTF8.GetBytes(key), aes.KeySize / 8);
aes.IV = AdjustKeySize(Encoding.UTF8.GetBytes(iv), aes.BlockSize / 8);
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using MemoryStream ms = new(Convert.FromBase64String(cipherText));
using CryptoStream cs = new(ms, decryptor, CryptoStreamMode.Read);
using StreamReader sr = new(cs);
return sr.ReadToEnd();
}
public static EncryptionParameters GenerateParameters()
{
using Aes aes = Aes.Create();
aes.KeySize = KeyByteLength * 8;
aes.GenerateKey();
aes.GenerateIV();
return new EncryptionParameters
{
Key = Convert.ToBase64String(aes.Key),
IV = Convert.ToBase64String(aes.IV)
};
}
private static byte[] AdjustKeySize(byte[] key, int size)
{
if (key.Length < size)
Array.Resize(ref key, size);
else if (key.Length > size)
Array.Resize(ref key, size);
return key;
}
}
}

View File

@@ -0,0 +1,9 @@
namespace DigitalData.UserManager.Application.Services.Options
{
public class EncryptionParameters
{
public required string Key { get; init; }
public required string IV { get; init; }
}
}