Add code for opening vault
This commit is contained in:
@@ -4,10 +4,8 @@ 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;
|
||||
@@ -21,15 +19,6 @@ public partial class App : Application
|
||||
|
||||
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();
|
||||
//command.CommandText = "SELECT quote($newPassword);";
|
||||
//command.Parameters.AddWithValue("$newPassword", "Test123");
|
||||
@@ -65,7 +54,6 @@ public partial class App : Application
|
||||
services.AddTransient<IKeyDeriver, KeyDeriver>();
|
||||
|
||||
services.AddTransient<IVaultKeyFactory, VaultKeyFactory>();
|
||||
services.AddTransient<IVaultInitializer, VaultInitializer>();
|
||||
services.AddTransient<IVaultStorage, VaultStorage>();
|
||||
services.TryAddSingleton<IContainer<VaultKey>, Container<VaultKey>>();
|
||||
services.TryAddSingleton<IContainer<VaultStorageConnection>, Container<VaultStorageConnection>>();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System.Text;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
@@ -15,10 +16,22 @@ public class CreateVaultHandler(IVaultComponentFactory componentFactory) :
|
||||
{
|
||||
if (componentFactory.Create(name) is IComponentHost host)
|
||||
{
|
||||
IVaultInitializer initializer = host.Services.GetRequiredService<IVaultInitializer>();
|
||||
if (await initializer.Initialize(name, password))
|
||||
IVaultKeyFactory keyVaultFactory = host.Services.GetRequiredService<IVaultKeyFactory>();
|
||||
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();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace Bitvault;
|
||||
|
||||
public interface IVaultInitializer
|
||||
{
|
||||
Task<bool> Initialize(string name, string password);
|
||||
}
|
||||
@@ -2,5 +2,7 @@
|
||||
|
||||
public interface IVaultKeyFactory
|
||||
{
|
||||
VaultKey Create(string password);
|
||||
VaultKey Create(byte[] phrase,
|
||||
byte[]? encryptedKey = null,
|
||||
byte[]? salt = null);
|
||||
}
|
||||
|
||||
@@ -1,20 +1,30 @@
|
||||
using Toolkit.Foundation;
|
||||
using System.Text;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class OpenVaultHandler(IMediator mediator) :
|
||||
public class OpenVaultHandler(VaultConfiguration configuration,
|
||||
IVaultKeyFactory keyVaultFactory,
|
||||
IVaultStorage vaultStorage) :
|
||||
IHandler<Open<Vault>, bool>
|
||||
{
|
||||
public async Task<bool> Handle(Open<Vault> args,
|
||||
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))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
// }
|
||||
//}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
namespace Bitvault;
|
||||
|
||||
public record VaultKey(byte[] Phrase, byte[] Public, byte[] Private) :
|
||||
public record VaultKey(byte[] Salt, byte[] EncryptedKey, byte[] DecryptedKey) :
|
||||
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);
|
||||
Array.Clear(Salt, 0, Salt.Length);
|
||||
Array.Clear(EncryptedKey, 0, EncryptedKey.Length);
|
||||
Array.Clear(DecryptedKey, 0, DecryptedKey.Length);
|
||||
}
|
||||
}
|
||||
@@ -8,17 +8,17 @@ public class VaultKeyFactory(IKeyGenerator generator,
|
||||
IDecryptor decryptor) :
|
||||
IVaultKeyFactory
|
||||
{
|
||||
public VaultKey Create(string password)
|
||||
public VaultKey Create(byte[] phrase,
|
||||
byte[]? encryptedKey = null,
|
||||
byte[]? salt = null)
|
||||
{
|
||||
byte[] salt = generator.Generate(16);
|
||||
byte[] key = generator.Generate(32);
|
||||
salt ??= generator.Generate(16);
|
||||
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);
|
||||
byte[] privateKey = decryptor.Decrypt(publicKey, derivedKey);
|
||||
|
||||
return new VaultKey(salt, publicKey, privateKey);
|
||||
return new VaultKey(salt, encryptedKey, decryptedKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ public class VaultStorage(IContainer<VaultStorageConnection> connection,
|
||||
VaultKey key)
|
||||
{
|
||||
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>>();
|
||||
using VaultDbContext context = await dbContextFactory.CreateDbContextAsync();
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Bitvault;
|
||||
|
||||
public class VaultStorageConnection(string connection)
|
||||
{
|
||||
private readonly string connection = connection;
|
||||
|
||||
public override string ToString() => connection;
|
||||
}
|
||||
Reference in New Issue
Block a user