WIP Windows User Accounts Composite Key integration

This commit is contained in:
BONNEVILLE Geoffroy
2017-12-20 18:49:11 +01:00
parent dfa3a21e6b
commit acb196d9c2
15 changed files with 112 additions and 35 deletions

View File

@@ -339,10 +339,6 @@
<HintPath>..\packages\Microsoft.Toolkit.Uwp.Notifications.2.0.0\lib\dotnet\Microsoft.Toolkit.Uwp.Notifications.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ModernKeePassLib, Version=2.37.0.2000, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ModernKeePassLib.2.37.8000\lib\netstandard1.2\ModernKeePassLib.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Splat.2.0.0\lib\Portable-Win81+Wpa81\Splat.dll</HintPath>
<Private>True</Private>
@@ -435,7 +431,12 @@
<Content Include="Assets\Wide310x150Logo.scale-180.png" />
<Content Include="Assets\Wide310x150Logo.scale-80.png" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<ProjectReference Include="..\ModernKeePassLib\ModernKeePassLib.csproj">
<Project>{2e710089-9559-4967-846c-e763dd1f3acb}</Project>
<Name>ModernKeePassLib</Name>
</ProjectReference>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '12.0' ">
<VisualStudioVersion>12.0</VisualStudioVersion>
</PropertyGroup>

View File

@@ -270,4 +270,7 @@
<data name="SettingsMenuItemSecurity" xml:space="preserve">
<value>Security</value>
</data>
<data name="CompositeKeyErrorUserAccount" xml:space="preserve">
<value>user account</value>
</data>
</root>

View File

@@ -171,6 +171,9 @@
<data name="CompositeKeyPassword.PlaceholderText" xml:space="preserve">
<value>Password</value>
</data>
<data name="CompositeKeyUserAccount.Text" xml:space="preserve">
<value>Windows User Account</value>
</data>
<data name="DonateButton.Content" xml:space="preserve">
<value>Donate</value>
</data>

View File

@@ -271,4 +271,7 @@
<data name="SettingsMenuItemSecurity" xml:space="preserve">
<value>Sécurité</value>
</data>
<data name="CompositeKeyErrorUserAccount" xml:space="preserve">
<value>compte utilisateur</value>
</data>
</root>

View File

@@ -171,6 +171,9 @@
<data name="CompositeKeyPassword.PlaceholderText" xml:space="preserve">
<value>Mot de passe</value>
</data>
<data name="CompositeKeyUserAccount.Text" xml:space="preserve">
<value>Compte Utilisateur Windows</value>
</data>
<data name="DonateButton.Content" xml:space="preserve">
<value>Donner</value>
</data>

View File

@@ -44,7 +44,17 @@ namespace ModernKeePass.ViewModels
}
}
public bool IsValid => !_isOpening && (HasPassword || HasKeyFile && KeyFile != null);
public bool HasUserAccount
{
get { return _hasUserAccount; }
set
{
SetProperty(ref _hasUserAccount, value);
OnPropertyChanged("IsValid");
}
}
public bool IsValid => !_isOpening && (HasPassword || HasKeyFile && KeyFile != null || HasUserAccount);
public string Status
{
@@ -91,8 +101,10 @@ namespace ModernKeePass.ViewModels
public double PasswordComplexityIndicator => QualityEstimation.EstimatePasswordBits(Password?.ToCharArray());
private bool _hasPassword;
private bool _hasKeyFile;
private bool _hasUserAccount;
private bool _isOpening;
private string _password = string.Empty;
private string _status;
@@ -136,6 +148,7 @@ namespace ModernKeePass.ViewModels
if (HasPassword) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserPassword"));
if (HasPassword && HasKeyFile) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserOr"));
if (HasKeyFile) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserKeyFile"));
if (HasKeyFile) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserAccount"));
UpdateStatus(errorMessage.ToString(), StatusTypes.Error);
break;
case DatabaseService.DatabaseStatus.Error:
@@ -169,6 +182,7 @@ namespace ModernKeePass.ViewModels
var compositeKey = new CompositeKey();
if (HasPassword) compositeKey.AddUserKey(new KcpPassword(Password));
if (HasKeyFile && KeyFile != null) compositeKey.AddUserKey(new KcpKeyFile(IOConnectionInfo.FromFile(KeyFile)));
if (HasUserAccount) compositeKey.AddUserKey(new KcpUserAccount());
return compositeKey;
}
}

View File

@@ -96,7 +96,6 @@ namespace ModernKeePass.ViewModels
private bool _isEditMode;
private PwEntry _reorderedEntry;
private ObservableCollection<EntryVm> _entries = new ObservableCollection<EntryVm>();
private string _filter = string.Empty;
private bool _isMenuClosed = true;
public GroupVm() {}

View File

@@ -169,7 +169,6 @@ namespace ModernKeePass.Views
Frame.Navigate(typeof(EntryDetailPage), entry);
}
private void GroupDetailPage_OnSizeChanged(object sender, SizeChangedEventArgs e)
{
VisualStateManager.GoToState(this, e.NewSize.Width < 700 ? "Small" : "Large", true);

View File

@@ -31,6 +31,7 @@
<RowDefinition Height="45" />
<RowDefinition Height="40" />
<RowDefinition Height="40" />
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<CheckBox Grid.Row="0" Grid.Column="0" IsChecked="{Binding HasPassword, Mode=TwoWay}" />
@@ -55,7 +56,9 @@
</ToolTipService.ToolTip>
</SymbolIcon>
</HyperlinkButton>
<TextBlock Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="3" Height="28" FontSize="14" FontWeight="Light" Text="{Binding Status}" Foreground="{Binding StatusType, Converter={StaticResource DiscreteIntToSolidColorBrushConverter}}" Visibility="{Binding Status, Converter={StaticResource EmptyStringToVisibilityConverter}}" />
<Button Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2" Content="{Binding ButtonLabel, ElementName=UserControl}" Click="OpenButton_OnClick" Background="{ThemeResource ListViewItemSelectedPointerOverBorderThemeBrush}" Foreground="{ThemeResource TextBoxBackgroundThemeBrush}" IsEnabled="{Binding IsValid}" />
<CheckBox Grid.Row="2" Grid.Column="0" IsChecked="{Binding HasUserAccount, Mode=TwoWay}" />
<TextBlock Grid.Row="2" Grid.Column="1" x:Uid="CompositeKeyUserAccount" FontSize="14" VerticalAlignment="Center" />
<Button Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="3" Content="{Binding ButtonLabel, ElementName=UserControl}" Click="OpenButton_OnClick" Background="{ThemeResource ListViewItemSelectedPointerOverBorderThemeBrush}" Foreground="{ThemeResource TextBoxBackgroundThemeBrush}" IsEnabled="{Binding IsValid}" />
<TextBlock Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="4" Height="28" FontSize="14" FontWeight="Light" Text="{Binding Status}" Foreground="{Binding StatusType, Converter={StaticResource DiscreteIntToSolidColorBrushConverter}}" Visibility="{Binding Status, Converter={StaticResource EmptyStringToVisibilityConverter}}" />
</Grid>
</UserControl>

View File

@@ -0,0 +1,54 @@
using System;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Security.Cryptography.DataProtection;
using Windows.Storage.Streams;
using ModernKeePassLib.Native;
namespace ModernKeePassLib.Cryptography
{
public static class ProtectedData
{
public static byte[] Protect(byte[] userData, byte[] optionalEntropy, DataProtectionScope scope)
{
var provider =
new DataProtectionProvider(scope == DataProtectionScope.CurrentUser ? "LOCAL=user" : "LOCAL=machine");
// Encode the plaintext input message to a buffer.
var buffMsg = userData.AsBuffer();
// Encrypt the message.
IBuffer buffProtected;
try
{
buffProtected = provider.ProtectAsync(buffMsg).GetAwaiter().GetResult();
}
catch (Exception e)
{
throw;
}
return buffProtected.ToArray();
}
public static byte[] Unprotect(byte[] userData, byte[] optionalEntropy, DataProtectionScope scope)
{
var provider =
new DataProtectionProvider(scope == DataProtectionScope.CurrentUser ? "LOCAL=user" : "LOCAL=machine");
// Decode the encrypted input message to a buffer.
var buffMsg = userData.AsBuffer();
// Decrypt the message.
IBuffer buffUnprotected;
try
{
buffUnprotected = provider.UnprotectAsync(buffMsg).GetAwaiter().GetResult();
}
catch (Exception e)
{
throw;
}
return buffUnprotected.ToArray();
}
}
}

View File

@@ -98,8 +98,9 @@ namespace ModernKeePassLib.Keys
#endif
strUserDir = UrlUtil.EnsureTerminatingSeparator(strUserDir, false);
strUserDir += PwDefs.ShortProductName;
#if !ModernKeePassLib
strUserDir += PwDefs.ShortProductName;
if(bCreate && !Directory.Exists(strUserDir))
Directory.CreateDirectory(strUserDir);
@@ -117,10 +118,13 @@ namespace ModernKeePassLib.Keys
{
string strFilePath = GetUserKeyFilePath(false);
#if ModernKeePassLib
var fileStream = StorageFile.GetFileFromPathAsync(strFilePath).GetAwaiter().GetResult().OpenStreamForReadAsync().GetAwaiter().GetResult();
var pbProtectedKey = new byte[(int)fileStream.Length];
fileStream.Read(pbProtectedKey, 0, (int)fileStream.Length);
fileStream.Dispose();
byte[] pbProtectedKey;
using (var fileStream = StorageFile.GetFileFromPathAsync(strFilePath).GetAwaiter().GetResult()
.OpenStreamForReadAsync().GetAwaiter().GetResult())
{
pbProtectedKey = new byte[(int) fileStream.Length];
fileStream.Read(pbProtectedKey, 0, (int) fileStream.Length);
}
#else
byte[] pbProtectedKey = File.ReadAllBytes(strFilePath);
#endif
@@ -148,9 +152,11 @@ namespace ModernKeePassLib.Keys
byte[] pbProtectedKey = ProtectedData.Protect(pbRandomKey,
m_pbEntropy, DataProtectionScope.CurrentUser);
#if ModernKeePassLib
var fileStream = StorageFile.GetFileFromPathAsync(strFilePath).GetAwaiter().GetResult().OpenStreamForWriteAsync().GetAwaiter().GetResult();
fileStream.Write(pbProtectedKey, 0, (int)fileStream.Length);
fileStream.Dispose();
using (var fileStream = StorageFile.GetFileFromPathAsync(strFilePath).GetAwaiter().GetResult()
.OpenStreamForWriteAsync().GetAwaiter().GetResult())
{
fileStream.Write(pbProtectedKey, 0, (int) fileStream.Length);
}
#else
File.WriteAllBytes(strFilePath, pbProtectedKey);
#endif

View File

@@ -81,6 +81,7 @@
<Compile Include="Cryptography\PasswordGenerator\PwCharSet.cs" />
<Compile Include="Cryptography\PasswordGenerator\PwProfile.cs" />
<Compile Include="Cryptography\PopularPasswords.cs" />
<Compile Include="Cryptography\ProtectedData.cs" />
<Compile Include="Cryptography\QualityEstimation.cs" />
<Compile Include="Cryptography\SelfTest.cs" />
<Compile Include="Interfaces\IStructureItem.cs" />

View File

@@ -2,7 +2,7 @@
<package >
<metadata>
<id>ModernKeePassLib</id>
<version>2.37.8000</version>
<version>2.37.9000</version>
<title>ModernKeePassLib</title>
<authors>Geoffroy Bonneville</authors>
<owners>Geoffroy Bonneville</owners>
@@ -10,7 +10,7 @@
<projectUrl>https://github.com/wismna/ModernKeePass</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Portable KeePass Password Management Library that targets .Net Standard and WinRT. Allows reading, editing and writing to KeePass 2.x databases.</description>
<releaseNotes>Code cleanup</releaseNotes>
<releaseNotes>Implements Windows User Accounts</releaseNotes>
<copyright>Copyright © 2017 Geoffroy Bonneville</copyright>
<tags>KeePass KeePassLib Portable PCL NetStandard</tags>
<dependencies>

View File

@@ -54,25 +54,12 @@ namespace ModernKeePassLib.Native
}
}
internal enum DataProtectionScope
public enum DataProtectionScope
{
CurrentUser,
LocalMachine
}
internal static class ProtectedData
{
public static byte[] Protect(byte[] userData, byte[] optionalEntropy, DataProtectionScope scope)
{
throw new NotImplementedException();
}
public static byte[] Unprotect(byte[] userData, byte[] optionalEntropy, DataProtectionScope scope)
{
throw new NotImplementedException();
}
}
internal enum MemoryProtectionScope
{
CrossProcess,

View File

@@ -34,6 +34,7 @@ using System.Security.Cryptography;
#endif
using ModernKeePassLib.Collections;
using ModernKeePassLib.Cryptography;
using ModernKeePassLib.Cryptography.PasswordGenerator;
using ModernKeePassLib.Native;
using ModernKeePassLib.Security;