From 4b05abad9b602f098044f8bba51ab58dd7016a6b Mon Sep 17 00:00:00 2001 From: TheXamlGuy Date: Thu, 2 May 2024 20:58:12 +0100 Subject: [PATCH] bunch of fixes --- .../Bitvault.Avalonia.Desktop.csproj | 2 ++ Bitvault.Avalonia/App.axaml.cs | 19 +++++++---- Bitvault/AesDecryptor.cs | 28 --------------- Bitvault/AesEncryptor.cs | 34 ------------------- Bitvault/CreateVaultHandler.cs | 21 +++++++----- Bitvault/IDecryptor.cs | 7 ---- Bitvault/IEncryptor.cs | 7 ---- Bitvault/IKeyDeriver.cs | 6 ---- Bitvault/IKeyGenerator.cs | 6 ---- Bitvault/IPasswordHasher.cs | 6 ---- Bitvault/IVaultFactory.cs | 7 ---- Bitvault/IVaultInitializer.cs | 6 ++++ ...ultKeyGenerator.cs => IVaultKeyFactory.cs} | 4 +-- Bitvault/IVaultStorage.cs | 2 +- Bitvault/KeyDeriver.cs | 13 ------- Bitvault/KeyGenerator.cs | 14 -------- Bitvault/OpenVaultHandler.cs | 5 +-- Bitvault/PasswordHasher.cs | 19 ----------- Bitvault/VaultFactory.cs | 13 ------- Bitvault/VaultInitializer.cs | 32 +++++++++++++++++ Bitvault/VaultKey.cs | 13 ++++++- ...aultKeyGenerator.cs => VaultKeyFactory.cs} | 9 +++-- Bitvault/VaultStorage.cs | 34 +++++++++++++++---- 23 files changed, 115 insertions(+), 192 deletions(-) delete mode 100644 Bitvault/AesDecryptor.cs delete mode 100644 Bitvault/AesEncryptor.cs delete mode 100644 Bitvault/IDecryptor.cs delete mode 100644 Bitvault/IEncryptor.cs delete mode 100644 Bitvault/IKeyDeriver.cs delete mode 100644 Bitvault/IKeyGenerator.cs delete mode 100644 Bitvault/IPasswordHasher.cs delete mode 100644 Bitvault/IVaultFactory.cs create mode 100644 Bitvault/IVaultInitializer.cs rename Bitvault/{IVaultKeyGenerator.cs => IVaultKeyFactory.cs} (63%) delete mode 100644 Bitvault/KeyDeriver.cs delete mode 100644 Bitvault/KeyGenerator.cs delete mode 100644 Bitvault/PasswordHasher.cs delete mode 100644 Bitvault/VaultFactory.cs create mode 100644 Bitvault/VaultInitializer.cs rename Bitvault/{VaultKeyGenerator.cs => VaultKeyFactory.cs} (79%) diff --git a/Bitvault.Avalonia.Desktop/Bitvault.Avalonia.Desktop.csproj b/Bitvault.Avalonia.Desktop/Bitvault.Avalonia.Desktop.csproj index 182cb26..292dd06 100644 --- a/Bitvault.Avalonia.Desktop/Bitvault.Avalonia.Desktop.csproj +++ b/Bitvault.Avalonia.Desktop/Bitvault.Avalonia.Desktop.csproj @@ -5,6 +5,8 @@ enable true app.manifest + true + win-x64 diff --git a/Bitvault.Avalonia/App.axaml.cs b/Bitvault.Avalonia/App.axaml.cs index d7c67d4..c298628 100644 --- a/Bitvault.Avalonia/App.axaml.cs +++ b/Bitvault.Avalonia/App.axaml.cs @@ -4,8 +4,11 @@ using Avalonia.Markup.Xaml; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using System; using Toolkit.Avalonia; using Toolkit.Foundation; +using System.IO; +using Microsoft.Extensions.DependencyInjection.Extensions; namespace Bitvault.Avalonia; @@ -61,17 +64,21 @@ public partial class App : Application services.AddTransient(); services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); services.AddTransient(); + services.TryAddSingleton, Container>(); + services.TryAddSingleton, Container>(); - services.AddDbContextFactory(args => + services.AddDbContextFactory((provider, args) => { - args.UseSqlite(); + if (provider.GetRequiredService>() + is IContainer connection) + { + args.UseSqlite($"{connection.Value}"); + } }); - services.AddDbContextFactory(); - services.AddHandler(); services.AddTemplate(); diff --git a/Bitvault/AesDecryptor.cs b/Bitvault/AesDecryptor.cs deleted file mode 100644 index 6e4d359..0000000 --- a/Bitvault/AesDecryptor.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Security.Cryptography; - -namespace Bitvault; - -public class AesDecryptor : - IDecryptor -{ - private const int IvSize = 16; - - public byte[] Decrypt(byte[] cipher, byte[] key) - { - Span iv = cipher.AsSpan(0, IvSize); - ReadOnlySpan 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(); - } -} diff --git a/Bitvault/AesEncryptor.cs b/Bitvault/AesEncryptor.cs deleted file mode 100644 index fec9065..0000000 --- a/Bitvault/AesEncryptor.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Security.Cryptography; - -namespace Bitvault; - -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(); - } -} diff --git a/Bitvault/CreateVaultHandler.cs b/Bitvault/CreateVaultHandler.cs index 46cddb1..abd9de6 100644 --- a/Bitvault/CreateVaultHandler.cs +++ b/Bitvault/CreateVaultHandler.cs @@ -1,25 +1,28 @@ using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using Toolkit.Foundation; namespace Bitvault; -public class CreateVaultHandler(IVaultComponentFactory vaultComponentFactory) : +public class CreateVaultHandler(IVaultComponentFactory componentFactory) : IHandler, bool> { - public Task Handle(Create args, + public async Task Handle(Create args, CancellationToken cancellationToken) { - if (args.Value is Vault vault && vault.Name is { Length: > 0 } name && vault.Password is { Length: > 0 } password) + if (args.Value is Vault vault && vault.Name is { Length: > 0 } name && + vault.Password is { Length: > 0 } password) { - if (vaultComponentFactory.Create(name) is IComponentHost host) + if (componentFactory.Create(name) is IComponentHost host) { - IVaultFactory factory = host.Services.GetRequiredService(); - factory.Create(name, password); - - return Task.FromResult(true); + IVaultInitializer initializer = host.Services.GetRequiredService(); + if (await initializer.Initialize(name, password)) + { + host.Start(); + } } } - return Task.FromResult(false); + return false; } } \ No newline at end of file diff --git a/Bitvault/IDecryptor.cs b/Bitvault/IDecryptor.cs deleted file mode 100644 index bfe8f27..0000000 --- a/Bitvault/IDecryptor.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Bitvault; - -public interface IDecryptor -{ - byte[] Decrypt(byte[] cipher, - byte[] key); -} \ No newline at end of file diff --git a/Bitvault/IEncryptor.cs b/Bitvault/IEncryptor.cs deleted file mode 100644 index c438b36..0000000 --- a/Bitvault/IEncryptor.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Bitvault; - -public interface IEncryptor -{ - - byte[] Encrypt(byte[] data, byte[] key); -} \ No newline at end of file diff --git a/Bitvault/IKeyDeriver.cs b/Bitvault/IKeyDeriver.cs deleted file mode 100644 index a181c48..0000000 --- a/Bitvault/IKeyDeriver.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Bitvault; - -public interface IKeyDeriver -{ - byte[] DeriveKey(string password, byte[] salt, int keySize = 32, int iterations = 10000); -} diff --git a/Bitvault/IKeyGenerator.cs b/Bitvault/IKeyGenerator.cs deleted file mode 100644 index e6536a4..0000000 --- a/Bitvault/IKeyGenerator.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Bitvault; - -public interface IKeyGenerator -{ - byte[] Generate(int size); -} \ No newline at end of file diff --git a/Bitvault/IPasswordHasher.cs b/Bitvault/IPasswordHasher.cs deleted file mode 100644 index 27e66d0..0000000 --- a/Bitvault/IPasswordHasher.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Bitvault; - -public interface IPasswordHasher -{ - string HashPassword(string password, int iterations = 10000); -} \ No newline at end of file diff --git a/Bitvault/IVaultFactory.cs b/Bitvault/IVaultFactory.cs deleted file mode 100644 index 931155b..0000000 --- a/Bitvault/IVaultFactory.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Bitvault -{ - public interface IVaultFactory - { - bool Create(string name, string password); - } -} \ No newline at end of file diff --git a/Bitvault/IVaultInitializer.cs b/Bitvault/IVaultInitializer.cs new file mode 100644 index 0000000..4054b05 --- /dev/null +++ b/Bitvault/IVaultInitializer.cs @@ -0,0 +1,6 @@ +namespace Bitvault; + +public interface IVaultInitializer +{ + Task Initialize(string name, string password); +} diff --git a/Bitvault/IVaultKeyGenerator.cs b/Bitvault/IVaultKeyFactory.cs similarity index 63% rename from Bitvault/IVaultKeyGenerator.cs rename to Bitvault/IVaultKeyFactory.cs index 5f6521c..3d5bda2 100644 --- a/Bitvault/IVaultKeyGenerator.cs +++ b/Bitvault/IVaultKeyFactory.cs @@ -1,6 +1,6 @@ namespace Bitvault; -public interface IVaultKeyGenerator +public interface IVaultKeyFactory { VaultKey Create(string password); -} \ No newline at end of file +} diff --git a/Bitvault/IVaultStorage.cs b/Bitvault/IVaultStorage.cs index 1961e31..cd11ca6 100644 --- a/Bitvault/IVaultStorage.cs +++ b/Bitvault/IVaultStorage.cs @@ -2,5 +2,5 @@ public interface IVaultStorage { - bool Create(string name, VaultKey key); + Task CreateAsync(string name, VaultKey key); } \ No newline at end of file diff --git a/Bitvault/KeyDeriver.cs b/Bitvault/KeyDeriver.cs deleted file mode 100644 index f82e14d..0000000 --- a/Bitvault/KeyDeriver.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Security.Cryptography; - -namespace Bitvault; - -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); - } -} diff --git a/Bitvault/KeyGenerator.cs b/Bitvault/KeyGenerator.cs deleted file mode 100644 index 3ee74d9..0000000 --- a/Bitvault/KeyGenerator.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Security.Cryptography; -namespace Bitvault; - -public class KeyGenerator : - IKeyGenerator -{ - public byte[] Generate(int size) - { - byte[] key = new byte[size]; - RandomNumberGenerator.Fill(key); - - return key; - } -} diff --git a/Bitvault/OpenVaultHandler.cs b/Bitvault/OpenVaultHandler.cs index d975b70..adab259 100644 --- a/Bitvault/OpenVaultHandler.cs +++ b/Bitvault/OpenVaultHandler.cs @@ -12,10 +12,7 @@ public class OpenVaultHandler(IMediator mediator) : { if (vault.Password is { Length: > 0 } password) { - //if (await mediator.Handle, bool>(Open.As(new VaultStorage("Personal", password)), cancellationToken)) - //{ - // return true; - //} + } } diff --git a/Bitvault/PasswordHasher.cs b/Bitvault/PasswordHasher.cs deleted file mode 100644 index b077e8f..0000000 --- a/Bitvault/PasswordHasher.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Security.Cryptography; - -namespace Bitvault; - -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)}"; - } -} diff --git a/Bitvault/VaultFactory.cs b/Bitvault/VaultFactory.cs deleted file mode 100644 index 28576e2..0000000 --- a/Bitvault/VaultFactory.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Bitvault; - -public class VaultFactory(IVaultKeyGenerator keyGenerator, - IVaultStorage vaultStorageFactory) : - IVaultFactory -{ - public bool Create(string name, - string password) - { - VaultKey key = keyGenerator.Create(password); - return vaultStorageFactory.Create(name, key); - } -} diff --git a/Bitvault/VaultInitializer.cs b/Bitvault/VaultInitializer.cs new file mode 100644 index 0000000..d8e5855 --- /dev/null +++ b/Bitvault/VaultInitializer.cs @@ -0,0 +1,32 @@ +using Toolkit.Foundation; + +namespace Bitvault; + +public class VaultStorageConnection(string connection) +{ + private readonly string connection = connection; + + public override string ToString() => connection; +} + +public class VaultInitializer(IVaultKeyFactory keyVaultFactory, + IContainer vaultKeyContainer, + IVaultStorage vaultStorage, + IWritableConfiguration configuration) : + IVaultInitializer +{ + public async Task Initialize(string name, + string password) + { + VaultKey key = keyVaultFactory.Create(password); + vaultKeyContainer.Set(key); + + if (await vaultStorage.CreateAsync(name, key)) + { + configuration.Write(args => args.Key = $"{Convert.ToBase64String(key.Phrase)}:{Convert.ToBase64String(key.Public)}"); + return true; + } + + return false; + } +} diff --git a/Bitvault/VaultKey.cs b/Bitvault/VaultKey.cs index 2ef97c9..a61ddcb 100644 --- a/Bitvault/VaultKey.cs +++ b/Bitvault/VaultKey.cs @@ -1,3 +1,14 @@ namespace Bitvault; -public record VaultKey(byte[] Salt, byte[] Public, byte[] Private); +public record VaultKey(byte[] Phrase, byte[] Public, byte[] Private) : + IDisposable +{ + public void Dispose() + { + GC.SuppressFinalize(this); + + Array.Clear(Phrase, 0, Phrase.Length); + Array.Clear(Public, 0, Public.Length); + Array.Clear(Private, 0, Private.Length); + } +} \ No newline at end of file diff --git a/Bitvault/VaultKeyGenerator.cs b/Bitvault/VaultKeyFactory.cs similarity index 79% rename from Bitvault/VaultKeyGenerator.cs rename to Bitvault/VaultKeyFactory.cs index 95f47b7..0c1c2ac 100644 --- a/Bitvault/VaultKeyGenerator.cs +++ b/Bitvault/VaultKeyFactory.cs @@ -1,10 +1,12 @@ -namespace Bitvault; +using Toolkit.Foundation; -public class VaultKeyGenerator(IKeyGenerator generator, +namespace Bitvault; + +public class VaultKeyFactory(IKeyGenerator generator, IKeyDeriver deriver, IEncryptor encryptor, IDecryptor decryptor) : - IVaultKeyGenerator + IVaultKeyFactory { public VaultKey Create(string password) { @@ -19,3 +21,4 @@ public class VaultKeyGenerator(IKeyGenerator generator, return new VaultKey(salt, publicKey, privateKey); } } + diff --git a/Bitvault/VaultStorage.cs b/Bitvault/VaultStorage.cs index d499ec6..8a4759d 100644 --- a/Bitvault/VaultStorage.cs +++ b/Bitvault/VaultStorage.cs @@ -1,17 +1,39 @@ using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Toolkit.Foundation; namespace Bitvault; -public class VaultStorage(IHostEnvironment environment, - IDbContextFactory dbContextFactory) : +public class VaultStorage(IContainer connection, + IHostEnvironment environment, + IServiceProvider provider) : IVaultStorage { - public bool Create(string name, VaultKey key) + public async Task CreateAsync(string name, + VaultKey key) { - using VaultDbContext context = dbContextFactory.CreateDbContext(); - context.Database.SetConnectionString($"Data Source={Path.Combine(environment.ContentRootPath, name)}" + - $".vault;Mode=ReadWriteCreate;Password={Convert.ToBase64String(key.Private)}"); + connection.Set(new VaultStorageConnection($"Data Source={Path.Combine(environment.ContentRootPath, name)}" + + $".vault;Mode=ReadWriteCreate;Pooling=false;Password={Convert.ToBase64String(key.Private)}")); + + IDbContextFactory dbContextFactory = provider.GetRequiredService>(); + using VaultDbContext context = await dbContextFactory.CreateDbContextAsync(); + + try + { + await Task.Run(async () => + { + await context.Database.EnsureCreatedAsync().ConfigureAwait(false); + await context.Database.CloseConnectionAsync().ConfigureAwait(false); + + context.Database.SetConnectionString(null); + + }).ConfigureAwait(false); + } + catch + { + return false; + } return true; }