Initial commit: SWP.Core enterprise framework with multi-tenant architecture, configuration management, security, telemetry and comprehensive test suite
This commit is contained in:
commit
5275a75502
87 changed files with 6140 additions and 0 deletions
28
Core/MultiKeyEncryption/MasterKey.cs
Normal file
28
Core/MultiKeyEncryption/MasterKey.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
namespace SWP.Core.MultiKeyEncryption
|
||||
{
|
||||
internal class MasterKey
|
||||
{
|
||||
public async Task RotateMasterKey(int tenantId, string oldMasterKey, string newMasterKey)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
// Hent alle bruger-keys for tenant
|
||||
//var users = await GetTenantUsers(tenantId);
|
||||
|
||||
//// Dekrypter connection string med gammel master key
|
||||
//var connString = DecryptWithKey(encryptedConnString, oldMasterKey);
|
||||
|
||||
//// Krypter med ny master key
|
||||
//var newEncryptedConnString = EncryptWithKey(connString, newMasterKey);
|
||||
|
||||
//// Re-krypter master key for alle brugere
|
||||
//foreach (var user in users)
|
||||
//{
|
||||
// var userKey = DeriveKeyFromPassword(user.Password);
|
||||
// var newEncryptedMasterKey = EncryptWithKey(newMasterKey, userKey);
|
||||
// await UpdateUserMasterKey(user.UserId, newEncryptedMasterKey);
|
||||
//}
|
||||
|
||||
//await UpdateTenantConnectionString(tenantId, newEncryptedConnString);
|
||||
}
|
||||
}
|
||||
}
|
||||
98
Core/MultiKeyEncryption/SecureConnectionString.cs
Normal file
98
Core/MultiKeyEncryption/SecureConnectionString.cs
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SWP.Core.MultiKeyEncryption
|
||||
{
|
||||
public class SecureConnectionString
|
||||
{
|
||||
const string _masterKey = "5AFD74B1C26E87FE6656099E850DC67A";
|
||||
|
||||
public class EncryptedData
|
||||
{
|
||||
public string EncryptedConnectionString { get; set; }
|
||||
public Dictionary<string, string> UserMasterKeys { get; set; } = new();
|
||||
}
|
||||
|
||||
public EncryptedData EncryptConnectionString(string connectionString)
|
||||
{
|
||||
var encryptedConnString = EncryptWithKey(connectionString, _masterKey);
|
||||
var userKeys = new Dictionary<string, string>();
|
||||
|
||||
|
||||
|
||||
return new EncryptedData
|
||||
{
|
||||
EncryptedConnectionString = encryptedConnString,
|
||||
UserMasterKeys = userKeys
|
||||
};
|
||||
}
|
||||
|
||||
public string AddNewUser(string username, string password)
|
||||
{
|
||||
var userKey = DeriveKeyFromPassword(password);
|
||||
var encryptedMasterKey = EncryptWithKey(_masterKey, userKey);
|
||||
return encryptedMasterKey;
|
||||
}
|
||||
|
||||
public string Decrypt(string encryptedConnString, string encryptedMasterKey, string password)
|
||||
{
|
||||
var userKey = DeriveKeyFromPassword(password);
|
||||
var masterKey = DecryptWithKey(encryptedMasterKey, userKey);
|
||||
return DecryptWithKey(encryptedConnString, masterKey);
|
||||
}
|
||||
|
||||
private string DeriveKeyFromPassword(string password)
|
||||
{
|
||||
using var deriveBytes = new Rfc2898DeriveBytes(
|
||||
password,
|
||||
new byte[16], // Fast salt for simpelhed - i produktion bør dette være unikt per bruger
|
||||
10000,
|
||||
HashAlgorithmName.SHA256);
|
||||
|
||||
return Convert.ToBase64String(deriveBytes.GetBytes(32));
|
||||
}
|
||||
|
||||
private string EncryptWithKey(string value, string key)
|
||||
{
|
||||
using var aes = Aes.Create();
|
||||
var keyBytes = Convert.FromBase64String(key);
|
||||
aes.Key = keyBytes;
|
||||
aes.GenerateIV();
|
||||
|
||||
using var encryptor = aes.CreateEncryptor();
|
||||
var valueBytes = Encoding.UTF8.GetBytes(value);
|
||||
var encrypted = encryptor.TransformFinalBlock(valueBytes, 0, valueBytes.Length);
|
||||
|
||||
var result = new byte[aes.IV.Length + encrypted.Length];
|
||||
Array.Copy(aes.IV, 0, result, 0, aes.IV.Length);
|
||||
Array.Copy(encrypted, 0, result, aes.IV.Length, encrypted.Length);
|
||||
|
||||
return Convert.ToBase64String(result);
|
||||
}
|
||||
|
||||
private string DecryptWithKey(string encryptedValue, string key)
|
||||
{
|
||||
var encryptedBytes = Convert.FromBase64String(encryptedValue);
|
||||
using var aes = Aes.Create();
|
||||
|
||||
var keyBytes = Convert.FromBase64String(key);
|
||||
aes.Key = keyBytes;
|
||||
|
||||
var iv = new byte[16];
|
||||
Array.Copy(encryptedBytes, 0, iv, 0, iv.Length);
|
||||
aes.IV = iv;
|
||||
|
||||
using var decryptor = aes.CreateDecryptor();
|
||||
var decrypted = decryptor.TransformFinalBlock(
|
||||
encryptedBytes,
|
||||
iv.Length,
|
||||
encryptedBytes.Length - iv.Length);
|
||||
|
||||
return Encoding.UTF8.GetString(decrypted);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue