This commit is contained in:
Chernykh Aleksandr
2025-12-05 01:02:53 +03:00
parent 67bf3487a0
commit 77b3aba94f
4 changed files with 107 additions and 38 deletions

View File

@@ -0,0 +1,18 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="KeyKeeper.PasswordEntryDialog"
Title="Введите пароль"
Width="300"
Height="180">
<StackPanel Margin="20" VerticalAlignment="Center">
<TextBlock Text="Введите мастер-пароль:" Margin="0,0,0,15"/>
<TextBox x:Name="PasswordBox" Margin="0,0,0,20"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="10">
<Button Content="Отмена" Width="80" Click="CancelButton_Click"/>
<Button Content="Открыть" Width="80" Click="OpenButton_Click"/>
</StackPanel>
</StackPanel>
</Window>

View File

@@ -0,0 +1,36 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace KeyKeeper
{
public partial class PasswordEntryDialog : Window
{
public string Password { get; private set; } = "";
public bool Opened { get; private set; } = false;
public PasswordEntryDialog()
{
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private void OpenButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
var passwordBox = this.FindControl<TextBox>("PasswordBox");
Password = passwordBox?.Text ?? "";
Opened = true;
Close();
}
private void CancelButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
Opened = false;
Close();
}
}
}

View File

@@ -7,9 +7,10 @@ using KeyKeeper.PasswordStore.Crypto;
namespace KeyKeeper; namespace KeyKeeper;
public partial class RepositoryWindow: Window public partial class RepositoryWindow : Window
{ {
public IPassStore? PassStore { private get; init; } public IPassStore? PassStore { get; init; }
public string? MasterPassword { get; init; } // <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
public RepositoryWindow() public RepositoryWindow()
{ {
@@ -19,7 +20,12 @@ public partial class RepositoryWindow: Window
protected override void OnOpened(EventArgs e) protected override void OnOpened(EventArgs e)
{ {
base.OnOpened(e); base.OnOpened(e);
if (PassStore!.Locked)
PassStore.Unlock(new CompositeKey("blablabla", null)); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
if (PassStore != null && PassStore.Locked && !string.IsNullOrEmpty(MasterPassword))
{
var compositeKey = new CompositeKey(MasterPassword, null);
PassStore.Unlock(compositeKey);
}
} }
} }

View File

@@ -4,6 +4,7 @@ using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using KeyKeeper.PasswordStore; using KeyKeeper.PasswordStore;
using KeyKeeper.PasswordStore.Crypto;
using KeyKeeper.ViewModels; using KeyKeeper.ViewModels;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -21,7 +22,6 @@ namespace KeyKeeper.Views
private async void CreateNewVault_Click(object sender, RoutedEventArgs e) private async void CreateNewVault_Click(object sender, RoutedEventArgs e)
{ {
// 1. Открываем проводник
var file = await StorageProvider.SaveFilePickerAsync(new FilePickerSaveOptions var file = await StorageProvider.SaveFilePickerAsync(new FilePickerSaveOptions
{ {
Title = "Создать новое хранилище паролей", Title = "Создать новое хранилище паролей",
@@ -29,34 +29,32 @@ namespace KeyKeeper.Views
DefaultExtension = "kkp", DefaultExtension = "kkp",
FileTypeChoices = new[] FileTypeChoices = new[]
{ {
new FilePickerFileType("Хранилище KeyKeeper") new FilePickerFileType("Хранилище KeyKeeper")
{ {
Patterns = new[] { "*.kkp" } Patterns = new[] { "*.kkp" }
} }
} }
}); });
if (file != null) if (file != null)
{ {
if (file.TryGetLocalPath() is string path) if (file.TryGetLocalPath() is string path)
{ {
// 2. Открываем окно с паролем
var passwordDialog = new PasswordDialog(); var passwordDialog = new PasswordDialog();
await passwordDialog.ShowDialog(this); await passwordDialog.ShowDialog(this);
if (passwordDialog.Created && !string.IsNullOrEmpty(passwordDialog.Password))
// 3. Если нажали "Создать"
if (passwordDialog.Created)
{ {
// 4. Создаем хранилище с паролем var compositeKey = new CompositeKey(passwordDialog.Password, null);
var compositeKey = new PasswordStore.Crypto.CompositeKey(passwordDialog.Password, null); var passStoreAccessor = new PassStoreFileAccessor(
(DataContext as MainWindowViewModel)!.CreateVault(path); filename: path,
create: true,
// 5. Открываем окно хранилища createOptions: new StoreCreationOptions()
OpenRepositoryWindow(new PassStoreFileAccessor(path, true, new StoreCreationOptions() {
{ Key = compositeKey,
Key = compositeKey, LockTimeoutSeconds = 800
LockTimeoutSeconds = 800, });
})); IPassStore passStore = passStoreAccessor;
OpenRepositoryWindow(passStore, passwordDialog.Password);
} }
} }
} }
@@ -64,22 +62,21 @@ namespace KeyKeeper.Views
private async void OpenExistingVault_Click(object sender, RoutedEventArgs e) private async void OpenExistingVault_Click(object sender, RoutedEventArgs e)
{ {
// Открываем диалог выбора файла
var files = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions var files = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{ {
Title = "Открыть хранилище паролей", Title = "Открыть хранилище паролей",
AllowMultiple = false, AllowMultiple = false,
FileTypeFilter = new[] FileTypeFilter = new[]
{ {
new FilePickerFileType("Хранилище KeyKeeper") new FilePickerFileType("Хранилище KeyKeeper")
{ {
Patterns = new[] { "*.kkp" } Patterns = new[] { "*.kkp" }
}, },
new FilePickerFileType("Все файлы") new FilePickerFileType("Все файлы")
{ {
Patterns = new[] { "*.*" } Patterns = new[] { "*.*" }
} }
} }
}); });
if (files.Count > 0) if (files.Count > 0)
@@ -87,20 +84,32 @@ namespace KeyKeeper.Views
var file = files[0]; var file = files[0];
if (file.TryGetLocalPath() is string path) if (file.TryGetLocalPath() is string path)
{ {
(DataContext as MainWindowViewModel)!.OpenVault(path); var passwordDialog = new PasswordEntryDialog();
OpenRepositoryWindow(new PassStoreFileAccessor(path, false, null)); await passwordDialog.ShowDialog(this);
if (passwordDialog.Opened && !string.IsNullOrEmpty(passwordDialog.Password))
{
var passStoreAccessor = new PassStoreFileAccessor(
filename: path,
create: false,
createOptions: null);
IPassStore passStore = passStoreAccessor;
(DataContext as MainWindowViewModel)!.OpenVault(path);
OpenRepositoryWindow(passStore, passwordDialog.Password);
}
} }
} }
} }
private void OpenRepositoryWindow(IPassStore store) private void OpenRepositoryWindow(IPassStore passStore, string masterPassword)
{ {
var repositoryWindow = new RepositoryWindow() var repositoryWindow = new RepositoryWindow()
{ {
DataContext = this.DataContext, DataContext = this.DataContext,
PassStore = store, PassStore = passStore,
MasterPassword = masterPassword,
WindowStartupLocation = WindowStartupLocation.CenterScreen WindowStartupLocation = WindowStartupLocation.CenterScreen
}; };
repositoryWindow.Closed += (s, e) => this.Show(); repositoryWindow.Closed += (s, e) => this.Show();
repositoryWindow.Show(); repositoryWindow.Show();
this.Hide(); this.Hide();