Add code for opening vault
This commit is contained in:
@@ -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>>();
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace Bitvault;
|
|
||||||
|
|
||||||
public interface IVaultInitializer
|
|
||||||
{
|
|
||||||
Task<bool> Initialize(string name, string password);
|
|
||||||
}
|
|
||||||
@@ -2,5 +2,7 @@
|
|||||||
|
|
||||||
public interface IVaultKeyFactory
|
public interface IVaultKeyFactory
|
||||||
{
|
{
|
||||||
VaultKey Create(string password);
|
VaultKey Create(byte[] phrase,
|
||||||
|
byte[]? encryptedKey = null,
|
||||||
|
byte[]? salt = null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
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,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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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