Add code for opening vault

This commit is contained in:
TheXamlGuy
2024-05-02 23:07:47 +01:00
parent c324cf9542
commit c1613d765c
11 changed files with 54 additions and 112 deletions
-12
View File
@@ -4,10 +4,8 @@ using Avalonia.Markup.Xaml;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using System;
using Toolkit.Avalonia; using Toolkit.Avalonia;
using Toolkit.Foundation; using Toolkit.Foundation;
using System.IO;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
namespace Bitvault.Avalonia; namespace Bitvault.Avalonia;
@@ -21,15 +19,6 @@ public partial class App : Application
public override async void OnFrameworkInitializationCompleted() public override async void OnFrameworkInitializationCompleted()
{ {
//var connectionString = new SqliteConnectionStringBuilder(@"Filename=C:\\Users\\dan_c\\source\\repos\\Bitvault\\Bitvault.Avalonia.Desktop\\bin\\Debug\\net8.0\\SQssLite.sql")
//{
// Mode = SqliteOpenMode.ReadWriteCreate,
// Password = "Test123"
//}.ToString();
//var connection = new SqliteConnection(connectionString);
//connection.Open();
//var command = connection.CreateCommand(); //var command = connection.CreateCommand();
//command.CommandText = "SELECT quote($newPassword);"; //command.CommandText = "SELECT quote($newPassword);";
//command.Parameters.AddWithValue("$newPassword", "Test123"); //command.Parameters.AddWithValue("$newPassword", "Test123");
@@ -65,7 +54,6 @@ public partial class App : Application
services.AddTransient<IKeyDeriver, KeyDeriver>(); services.AddTransient<IKeyDeriver, KeyDeriver>();
services.AddTransient<IVaultKeyFactory, VaultKeyFactory>(); services.AddTransient<IVaultKeyFactory, VaultKeyFactory>();
services.AddTransient<IVaultInitializer, VaultInitializer>();
services.AddTransient<IVaultStorage, VaultStorage>(); services.AddTransient<IVaultStorage, VaultStorage>();
services.TryAddSingleton<IContainer<VaultKey>, Container<VaultKey>>(); services.TryAddSingleton<IContainer<VaultKey>, Container<VaultKey>>();
services.TryAddSingleton<IContainer<VaultStorageConnection>, Container<VaultStorageConnection>>(); services.TryAddSingleton<IContainer<VaultStorageConnection>, Container<VaultStorageConnection>>();
+15 -2
View File
@@ -1,5 +1,6 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using System.Text;
using Toolkit.Foundation; using Toolkit.Foundation;
namespace Bitvault; namespace Bitvault;
@@ -15,10 +16,22 @@ public class CreateVaultHandler(IVaultComponentFactory componentFactory) :
{ {
if (componentFactory.Create(name) is IComponentHost host) if (componentFactory.Create(name) is IComponentHost host)
{ {
IVaultInitializer initializer = host.Services.GetRequiredService<IVaultInitializer>(); IVaultKeyFactory keyVaultFactory = host.Services.GetRequiredService<IVaultKeyFactory>();
if (await initializer.Initialize(name, password)) IContainer<VaultKey> vaultKeyContainer = host.Services.GetRequiredService<IContainer<VaultKey>>();
IVaultStorage vaultStorage = host.Services.GetRequiredService<IVaultStorage>();
VaultKey key = keyVaultFactory.Create(Encoding.UTF8.GetBytes(password));
vaultKeyContainer.Set(key);
if (await vaultStorage.CreateAsync(name, key))
{ {
IWritableConfiguration<VaultConfiguration> configuration =
host.Services.GetRequiredService<IWritableConfiguration<VaultConfiguration>>();
configuration.Write(args => args.Key = $"{Convert.ToBase64String(key.Salt)}:{Convert.ToBase64String(key.EncryptedKey)}:{Convert.ToBase64String(key.DecryptedKey)}");
host.Start(); host.Start();
return true;
} }
} }
} }
-6
View File
@@ -1,6 +0,0 @@
namespace Bitvault;
public interface IVaultInitializer
{
Task<bool> Initialize(string name, string password);
}
+3 -1
View File
@@ -2,5 +2,7 @@
public interface IVaultKeyFactory public interface IVaultKeyFactory
{ {
VaultKey Create(string password); VaultKey Create(byte[] phrase,
byte[]? encryptedKey = null,
byte[]? salt = null);
} }
+15 -5
View File
@@ -1,18 +1,28 @@
using Toolkit.Foundation; using System.Text;
using Toolkit.Foundation;
namespace Bitvault; namespace Bitvault;
public class OpenVaultHandler(IMediator mediator) : public class OpenVaultHandler(VaultConfiguration configuration,
IVaultKeyFactory keyVaultFactory,
IVaultStorage vaultStorage) :
IHandler<Open<Vault>, bool> IHandler<Open<Vault>, bool>
{ {
public async Task<bool> Handle(Open<Vault> args, public async Task<bool> Handle(Open<Vault> args,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
if (args.Value is Vault vault) if (args.Value is Vault vault && configuration.Name is { Length: > 0 } name && vault.Password is { Length: > 0 } password)
{ {
if (vault.Password is { Length: > 0 } password) if (configuration.Key?.Split(':') is { Length: >= 2 } keyPart)
{ {
byte[]? salt = Convert.FromBase64String(keyPart[0]);
byte[]? encryptedKey = Convert.FromBase64String(keyPart[1]);
VaultKey key = keyVaultFactory.Create(Encoding.UTF8.GetBytes(password), encryptedKey, salt);
if (await vaultStorage.CreateAsync(name, key))
{
}
} }
} }
-41
View File
@@ -1,41 +0,0 @@
//using Microsoft.EntityFrameworkCore;
//using Microsoft.Extensions.Hosting;
//using Toolkit.Foundation;
//namespace Bitvault;
//public class OpenVaultStorageHandler(IHostEnvironment environment,
// IDbContextFactory<VaultDbContext> dbContextFactory) : IHandler<Open<VaultStorage>, bool>
//{
// public async Task<bool> Handle(Open<VaultStorage> args, CancellationToken cancellationToken)
// {
// if (args.Value is VaultStorage vault)
// {
// if (vault.Name is { Length: > 0 } name && vault.Password is { Length: > 0 } password)
// {
// using VaultDbContext context = dbContextFactory.CreateDbContext();
// var d = context.Database.GetDbConnection().ConnectionString;
// context.Database.SetConnectionString($"Data Source={Path.Combine(environment.ContentRootPath, name)}.vault;Mode=ReadWriteCreate;Password={password}");
// bool isOpen = false;
// await Task.Run(async () =>
// {
// try
// {
// await context.Database.OpenConnectionAsync();
// isOpen = true;
// }
// catch
// {
// // We are ignoring this exception as it is either a go, or not.
// }
// }, cancellationToken);
// return isOpen;
// }
// }
// return false;
// }
//}
-32
View File
@@ -1,32 +0,0 @@
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<VaultKey> vaultKeyContainer,
IVaultStorage vaultStorage,
IWritableConfiguration<VaultConfiguration> configuration) :
IVaultInitializer
{
public async Task<bool> 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;
}
}
+4 -4
View File
@@ -1,14 +1,14 @@
namespace Bitvault; namespace Bitvault;
public record VaultKey(byte[] Phrase, byte[] Public, byte[] Private) : public record VaultKey(byte[] Salt, byte[] EncryptedKey, byte[] DecryptedKey) :
IDisposable IDisposable
{ {
public void Dispose() public void Dispose()
{ {
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
Array.Clear(Phrase, 0, Phrase.Length); Array.Clear(Salt, 0, Salt.Length);
Array.Clear(Public, 0, Public.Length); Array.Clear(EncryptedKey, 0, EncryptedKey.Length);
Array.Clear(Private, 0, Private.Length); Array.Clear(DecryptedKey, 0, DecryptedKey.Length);
} }
} }
+8 -8
View File
@@ -8,17 +8,17 @@ public class VaultKeyFactory(IKeyGenerator generator,
IDecryptor decryptor) : IDecryptor decryptor) :
IVaultKeyFactory IVaultKeyFactory
{ {
public VaultKey Create(string password) public VaultKey Create(byte[] phrase,
byte[]? encryptedKey = null,
byte[]? salt = null)
{ {
byte[] salt = generator.Generate(16); salt ??= generator.Generate(16);
byte[] key = generator.Generate(32); byte[] derivedKey = deriver.DeriveKey(phrase, salt);
byte[] derivedKey = deriver.DeriveKey(password, salt); encryptedKey ??= encryptor.Encrypt(generator.Generate(32), derivedKey);
byte[] decryptedKey = decryptor.Decrypt(encryptedKey, derivedKey);
byte[] publicKey = encryptor.Encrypt(key, derivedKey); return new VaultKey(salt, encryptedKey, decryptedKey);
byte[] privateKey = decryptor.Decrypt(publicKey, derivedKey);
return new VaultKey(salt, publicKey, privateKey);
} }
} }
+1 -1
View File
@@ -14,7 +14,7 @@ public class VaultStorage(IContainer<VaultStorageConnection> connection,
VaultKey key) VaultKey key)
{ {
connection.Set(new VaultStorageConnection($"Data Source={Path.Combine(environment.ContentRootPath, name)}" + connection.Set(new VaultStorageConnection($"Data Source={Path.Combine(environment.ContentRootPath, name)}" +
$".vault;Mode=ReadWriteCreate;Pooling=false;Password={Convert.ToBase64String(key.Private)}")); $".vault;Mode=ReadWriteCreate;Pooling=false;Password={Convert.ToBase64String(key.DecryptedKey)}"));
IDbContextFactory<VaultDbContext> dbContextFactory = provider.GetRequiredService<IDbContextFactory<VaultDbContext>>(); IDbContextFactory<VaultDbContext> dbContextFactory = provider.GetRequiredService<IDbContextFactory<VaultDbContext>>();
using VaultDbContext context = await dbContextFactory.CreateDbContextAsync(); using VaultDbContext context = await dbContextFactory.CreateDbContextAsync();
+8
View File
@@ -0,0 +1,8 @@
namespace Bitvault;
public class VaultStorageConnection(string connection)
{
private readonly string connection = connection;
public override string ToString() => connection;
}