unlock error reporting, bugfixes

- fix Locked property becoming true when the store in fact was not opened
- fix password being null
- make RepositoryWindow non-resizeable
- show error popups in case of unlock error
This commit is contained in:
2025-12-05 15:30:38 +03:00
parent 4beca8f286
commit 84abdc1596
8 changed files with 88 additions and 12 deletions

View File

@@ -63,8 +63,8 @@ public class PassStoreFileAccessor : IPassStore
file.Seek((file.Position + 4096 - 1) / 4096 * 4096, SeekOrigin.Begin); file.Seek((file.Position + 4096 - 1) / 4096 * 4096, SeekOrigin.Begin);
key.Salt = hdr.PreSalt; key.Salt = hdr.PreSalt;
this.key = hdr.KdfInfo.GetKdf().Derive(key, 32); byte[] masterKey = hdr.KdfInfo.GetKdf().Derive(key, 32);
using OuterEncryptionReader cryptoReader = new(file, this.key, ((OuterAesHeader)hdr.OuterCryptoHeader).InitVector); using OuterEncryptionReader cryptoReader = new(file, masterKey, ((OuterAesHeader)hdr.OuterCryptoHeader).InitVector);
using BinaryReader rd = new(cryptoReader); using BinaryReader rd = new(cryptoReader);
{ {
@@ -103,6 +103,7 @@ public class PassStoreFileAccessor : IPassStore
throw PassStoreFileException.UnexpectedEndOfFile; throw PassStoreFileException.UnexpectedEndOfFile;
} }
} }
this.key = masterKey;
} }
public void Lock() public void Lock()

View File

@@ -3,6 +3,7 @@
xmlns:vm="using:KeyKeeper.ViewModels" xmlns:vm="using:KeyKeeper.ViewModels"
x:Class="KeyKeeper.RepositoryWindow" x:Class="KeyKeeper.RepositoryWindow"
Title="KeyKeeper - Хранилище паролей" Title="KeyKeeper - Хранилище паролей"
CanResize="False"
Width="800" Width="800"
Height="600" Height="600"
Background="White" Background="White"
@@ -13,7 +14,7 @@
<Grid> <Grid>
<!-- Синий левый край --> <!-- Синий левый край -->
<Border Width="200" <Border Width="200"
Background="#2328C4" Background="#2328C4"
HorizontalAlignment="Left" HorizontalAlignment="Left"
VerticalAlignment="Stretch"/> VerticalAlignment="Stretch"/>
<StackPanel Margin="20" HorizontalAlignment="Left"> <StackPanel Margin="20" HorizontalAlignment="Left">
@@ -42,8 +43,7 @@
</Border> </Border>
<!-- Save Passwords --> <!-- Save Passwords -->
<Button Content="Save Passwords" <Button Content="Save Passwords"
Width="120"
Height="30" Height="30"
Foreground="White" Foreground="White"
HorizontalAlignment="Left" HorizontalAlignment="Left"

View File

@@ -1,13 +1,20 @@
using System; using System;
using Avalonia.Controls; using Avalonia.Controls;
using KeyKeeper.ViewModels;
using KeyKeeper.Views;
namespace KeyKeeper; namespace KeyKeeper;
public partial class RepositoryWindow: Window public partial class RepositoryWindow: Window
{ {
public RepositoryWindow() public RepositoryWindow(RepositoryWindowViewModel model)
{ {
InitializeComponent(); InitializeComponent();
DataContext = model;
model.ShowErrorPopup = async (string message) =>
{
await new ErrorDialog(message).ShowDialog(this);
};
} }
protected override void OnOpened(EventArgs e) protected override void OnOpened(EventArgs e)

View File

@@ -10,7 +10,7 @@ public partial class LockedRepositoryViewModel : ViewModelBase
{ {
RepositoryWindowViewModel parent; RepositoryWindowViewModel parent;
private IPassStore passStore; private IPassStore passStore;
private string password; private string password = "";
public LockedRepositoryViewModel(IPassStore store, RepositoryWindowViewModel parent) public LockedRepositoryViewModel(IPassStore store, RepositoryWindowViewModel parent)
{ {
@@ -25,7 +25,7 @@ public partial class LockedRepositoryViewModel : ViewModelBase
} }
[RelayCommand] [RelayCommand]
public void TryUnlock() public async Task TryUnlock()
{ {
try try
{ {
@@ -33,12 +33,28 @@ public partial class LockedRepositoryViewModel : ViewModelBase
parent.UpdateLockStatus(); parent.UpdateLockStatus();
} catch (PassStoreFileException e) } catch (PassStoreFileException e)
{ {
// TODO
Console.WriteLine("pass store file exception: " + e.Message); Console.WriteLine("pass store file exception: " + e.Message);
if (e.Message == PassStoreFileException.ContentHMACMismatch.Message ||
e.Message == PassStoreFileException.InvalidBeginMarker.Message)
{
await parent.ShowErrorPopup("Incorrect password or corrupted file");
} else if (e.Message == PassStoreFileException.UnexpectedEndOfFile.Message ||
e.Message == PassStoreFileException.IncorrectMagicNumber.Message ||
e.Message == PassStoreFileException.InvalidCryptoHeader.Message ||
e.Message == PassStoreFileException.InvalidPassStoreEntry.Message)
{
await parent.ShowErrorPopup("Corrupted file");
} else if (e.Message == PassStoreFileException.UnsupportedVersion.Message)
{
await parent.ShowErrorPopup("Unsupported store file version");
} else
{
await parent.ShowErrorPopup("Unknown password store unlock error");
}
} catch (Exception e) } catch (Exception e)
{ {
// TODO
Console.WriteLine(e); Console.WriteLine(e);
await parent.ShowErrorPopup("Cannot open the password store file");
} }
} }
} }

View File

@@ -1,3 +1,5 @@
using System;
using System.Threading.Tasks;
using KeyKeeper.PasswordStore; using KeyKeeper.PasswordStore;
namespace KeyKeeper.ViewModels; namespace KeyKeeper.ViewModels;
@@ -7,6 +9,8 @@ public partial class RepositoryWindowViewModel : ViewModelBase
private object currentPage; private object currentPage;
private IPassStore passStore; private IPassStore passStore;
public Func<string, Task> ShowErrorPopup;
public object CurrentPage public object CurrentPage
{ {
get => currentPage; get => currentPage;

View File

@@ -0,0 +1,31 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="KeyKeeper.Views.ErrorDialog"
Width="350" Height="120"
Background="White"
CanResize="False"
Title="Error">
<Grid Margin="10" RowDefinitions="*,Auto">
<TextBlock x:Name="MessageText"
Grid.Row="0"
Foreground="Red"
FontSize="18"
TextWrapping="Wrap" />
<Button Grid.Row="1"
Content="OK"
HorizontalAlignment="Center"
Margin="0,10,0,0"
Click="Ok_Click"
Background="#aaa" />
<Grid.Styles>
<Style Selector="Button /template/ ContentPresenter">
<Setter Property="Foreground" Value="#333" />
</Style>
<Style Selector="Button:pointerover /template/ ContentPresenter">
<Setter Property="Background" Value="#ccc" />
<Setter Property="Foreground" Value="#444" />
</Style>
</Grid.Styles>
</Grid>
</Window>

View File

@@ -0,0 +1,18 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
namespace KeyKeeper.Views;
public partial class ErrorDialog : Window
{
public ErrorDialog(string message)
{
InitializeComponent();
MessageText.Text = message;
}
private void Ok_Click(object sender, RoutedEventArgs e)
{
Close();
}
}

View File

@@ -82,9 +82,8 @@ namespace KeyKeeper.Views
private void OpenRepositoryWindow(IPassStore store) private void OpenRepositoryWindow(IPassStore store)
{ {
var repositoryWindow = new RepositoryWindow() var repositoryWindow = new RepositoryWindow(new RepositoryWindowViewModel(store))
{ {
DataContext = new RepositoryWindowViewModel(store),
WindowStartupLocation = WindowStartupLocation.CenterScreen WindowStartupLocation = WindowStartupLocation.CenterScreen
}; };
repositoryWindow.Closed += (s, e) => this.Show(); repositoryWindow.Closed += (s, e) => this.Show();