From abcff30da6a0eb8f759260f781a0825b4de06593 Mon Sep 17 00:00:00 2001 From: TheXamlGuy Date: Fri, 3 May 2024 19:33:32 +0100 Subject: [PATCH] vault unlocking WIP --- Toolkit.Avalonia/AvaloniaDispatcher.cs | 5 +- Toolkit.Avalonia/ContentDialogHandler.cs | 2 +- Toolkit.Foundation/AesDecryptor.cs | 46 ++++++++++++----- Toolkit.Foundation/AesEncryptor.cs | 49 ++++++++++++------- Toolkit.Foundation/IDecryptor.cs | 5 +- Toolkit.Foundation/IDispatcher.cs | 2 +- Toolkit.Foundation/IEncryptor.cs | 5 +- .../ObservableCollectionViewModel.cs | 11 +++++ Toolkit.Foundation/Publisher.cs | 10 ++-- 9 files changed, 92 insertions(+), 43 deletions(-) diff --git a/Toolkit.Avalonia/AvaloniaDispatcher.cs b/Toolkit.Avalonia/AvaloniaDispatcher.cs index 0870623..1f190e6 100644 --- a/Toolkit.Avalonia/AvaloniaDispatcher.cs +++ b/Toolkit.Avalonia/AvaloniaDispatcher.cs @@ -6,8 +6,5 @@ namespace Toolkit.Avalonia; public class AvaloniaDispatcher : IDispatcher { - public async Task InvokeAsync(Action action) - { - await Dispatcher.UIThread.InvokeAsync(action); - } + public async Task Invoke(Action action) => await Dispatcher.UIThread.InvokeAsync(action); } \ No newline at end of file diff --git a/Toolkit.Avalonia/ContentDialogHandler.cs b/Toolkit.Avalonia/ContentDialogHandler.cs index 18c20d8..1f340c5 100644 --- a/Toolkit.Avalonia/ContentDialogHandler.cs +++ b/Toolkit.Avalonia/ContentDialogHandler.cs @@ -79,7 +79,7 @@ public class ContentDialogHandler(IDispatcher dispatcher) : async void DeactivateHandler(object? sender, EventArgs args) { deactivatable.DeactivateHandler -= DeactivateHandler; - await dispatcher.InvokeAsync(contentDialog.Hide); + await dispatcher.Invoke(contentDialog.Hide); } deactivatable.DeactivateHandler += DeactivateHandler; diff --git a/Toolkit.Foundation/AesDecryptor.cs b/Toolkit.Foundation/AesDecryptor.cs index 5ef8653..c988943 100644 --- a/Toolkit.Foundation/AesDecryptor.cs +++ b/Toolkit.Foundation/AesDecryptor.cs @@ -7,22 +7,44 @@ public class AesDecryptor : { private const int IvSize = 16; - public byte[] Decrypt(byte[] cipher, byte[] key) + public bool TryDecrypt(byte[] cipher, + byte[] key, + out byte[]? decryptedData) { - Span iv = cipher.AsSpan(0, IvSize); - ReadOnlySpan encryptedContent = cipher.AsSpan(IvSize); + decryptedData = null; - using Aes aes = Aes.Create(); - aes.Key = key; - aes.IV = iv.ToArray(); + if (cipher is null || key is null || cipher.Length < IvSize) + { + return false; + } - using MemoryStream memoryStream = new(encryptedContent.ToArray()); - using ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); - using CryptoStream cryptoStream = new(memoryStream, decryptor, CryptoStreamMode.Read); + try + { + Span iv = cipher.AsSpan(0, IvSize); + ReadOnlySpan encryptedContent = cipher.AsSpan(IvSize); - using MemoryStream resultStream = new(); - cryptoStream.CopyTo(resultStream); + using Aes aes = Aes.Create(); + aes.Key = key; + aes.IV = iv.ToArray(); - return resultStream.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); + + decryptedData = resultStream.ToArray(); + + return true; + } + catch (CryptographicException) + { + return false; + } + catch (Exception) + { + return false; + } } } diff --git a/Toolkit.Foundation/AesEncryptor.cs b/Toolkit.Foundation/AesEncryptor.cs index 9e844d3..08a3996 100644 --- a/Toolkit.Foundation/AesEncryptor.cs +++ b/Toolkit.Foundation/AesEncryptor.cs @@ -7,28 +7,43 @@ public class AesEncryptor : { private const int IvSize = 16; - public byte[] Encrypt(byte[] data, - byte[] key) + public bool TryEncrypt(byte[] data, + byte[] key, + out byte[]? encryptedData) { - if (key.Length != 32) + encryptedData = null; + + if (data is null || key is null || key.Length != 32) { - throw new ArgumentException("Key must be 256 bits (32 bytes)."); + return false; } - 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)) + try { - cryptoStream.Write(data, 0, data.Length); - cryptoStream.FlushFinalBlock(); - } + using Aes aes = Aes.Create(); + aes.Key = key; + aes.GenerateIV(); - return memoryStream.ToArray(); + using MemoryStream memoryStream = new(); + memoryStream.Write(aes.IV, 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(); + } + + encryptedData = memoryStream.ToArray(); + return true; + } + catch (CryptographicException) + { + return false; + } + catch (Exception) + { + return false; + } } } diff --git a/Toolkit.Foundation/IDecryptor.cs b/Toolkit.Foundation/IDecryptor.cs index 0a618f7..70c47c1 100644 --- a/Toolkit.Foundation/IDecryptor.cs +++ b/Toolkit.Foundation/IDecryptor.cs @@ -1,6 +1,7 @@ namespace Toolkit.Foundation; public interface IDecryptor { - byte[] Decrypt(byte[] cipher, - byte[] key); + bool TryDecrypt(byte[] cipher, + byte[] key, + out byte[]? decryptedData); } \ No newline at end of file diff --git a/Toolkit.Foundation/IDispatcher.cs b/Toolkit.Foundation/IDispatcher.cs index 7a4f6ce..86790e5 100644 --- a/Toolkit.Foundation/IDispatcher.cs +++ b/Toolkit.Foundation/IDispatcher.cs @@ -2,5 +2,5 @@ public interface IDispatcher { - Task InvokeAsync(Action action); + Task Invoke(Action action); } \ No newline at end of file diff --git a/Toolkit.Foundation/IEncryptor.cs b/Toolkit.Foundation/IEncryptor.cs index fc37690..755d3c7 100644 --- a/Toolkit.Foundation/IEncryptor.cs +++ b/Toolkit.Foundation/IEncryptor.cs @@ -1,5 +1,8 @@ namespace Toolkit.Foundation; + public interface IEncryptor { - byte[] Encrypt(byte[] data, byte[] key); + bool TryEncrypt(byte[] data, + byte[] key, + out byte[]? encryptedData); } \ No newline at end of file diff --git a/Toolkit.Foundation/ObservableCollectionViewModel.cs b/Toolkit.Foundation/ObservableCollectionViewModel.cs index 569f831..4ebc292 100644 --- a/Toolkit.Foundation/ObservableCollectionViewModel.cs +++ b/Toolkit.Foundation/ObservableCollectionViewModel.cs @@ -412,6 +412,17 @@ public partial class ObservableCollectionViewModel : CollectionChanged?.Invoke(this, args); } +public partial class ObservableCollectionViewModel(IServiceProvider provider, + IServiceFactory factory, + IMediator mediator, + IPublisher publisher, + ISubscriber subscriber, IDisposer disposer) : ObservableCollectionViewModel(provider, factory, mediator, publisher, subscriber, disposer) + where TViewModel : notnull +{ + [ObservableProperty] + private TValue? value; +} + public class ObservableCollectionViewModel(IServiceProvider provider, IServiceFactory factory, IMediator mediator, diff --git a/Toolkit.Foundation/Publisher.cs b/Toolkit.Foundation/Publisher.cs index ac17c94..6f1ce5a 100644 --- a/Toolkit.Foundation/Publisher.cs +++ b/Toolkit.Foundation/Publisher.cs @@ -73,29 +73,29 @@ public class Publisher(ISubscriptionManager subscriptionManager, public Task PublishUI(object key, CancellationToken cancellationToken = default) where TMessage : new() => - Publish(new TMessage(), args => dispatcher.InvokeAsync(async () => await args()), + Publish(new TMessage(), args => dispatcher.Invoke(async () => await args()), key, cancellationToken); public Task PublishUI(TMessage message, CancellationToken cancellationToken = default) where TMessage : notnull => - Publish(message, args => dispatcher.InvokeAsync(async () => await args()), + Publish(message, args => dispatcher.Invoke(async () => await args()), null, cancellationToken); public Task PublishUI(TMessage message, object key, CancellationToken cancellationToken = default) where TMessage : notnull => - Publish(message, args => dispatcher.InvokeAsync(async () => await args()), + Publish(message, args => dispatcher.Invoke(async () => await args()), key, cancellationToken); public Task PublishUI(CancellationToken cancellationToken = default) where TMessage : new() => - Publish(new TMessage(), args => dispatcher.InvokeAsync(async () => await args()), + Publish(new TMessage(), args => dispatcher.Invoke(async () => await args()), null, cancellationToken); public Task PublishUI(object message, CancellationToken cancellationToken = default) => Publish(message, args => - dispatcher.InvokeAsync(async () => await args()), + dispatcher.Invoke(async () => await args()), null, cancellationToken); } \ No newline at end of file