ModernKeePassLib custom PCL version

This commit is contained in:
2017-09-22 15:40:24 +02:00
parent baba70e56d
commit a43bc20eb3
98 changed files with 6049 additions and 3038 deletions

View File

@@ -1,7 +1,6 @@
using System; using System;
using Windows.Storage; using Windows.Storage;
using System.Threading.Tasks; using System.Threading.Tasks;
using ModernKeePass.ViewModels; using ModernKeePass.ViewModels;
using ModernKeePassLib; using ModernKeePassLib;
using ModernKeePassLib.Interfaces; using ModernKeePassLib.Interfaces;
@@ -23,13 +22,14 @@ namespace ModernKeePass.Common
{ {
this.databaseFile = databaseFile; this.databaseFile = databaseFile;
} }
public async Task<string> Open(string password) public string Open(string password)
{ {
var key = new CompositeKey(); var key = new CompositeKey();
try try
{ {
key.AddUserKey(new KcpPassword(password)); key.AddUserKey(new KcpPassword(password));
await _pwDatabase.Open(IOConnectionInfo.FromFile(databaseFile), key, new NullStatusLogger()); _pwDatabase.Open(IOConnectionInfo.FromFile(databaseFile), key, new NullStatusLogger());
//_pwDatabase.Open(IOConnectionInfo.FromPath(databaseFile.Path), key, new NullStatusLogger());
IsOpen = _pwDatabase.IsOpen; IsOpen = _pwDatabase.IsOpen;
Name = databaseFile.DisplayName; Name = databaseFile.DisplayName;
RootGroup = new GroupVm(_pwDatabase.RootGroup); RootGroup = new GroupVm(_pwDatabase.RootGroup);
@@ -42,6 +42,10 @@ namespace ModernKeePass.Common
{ {
return "Wrong password"; return "Wrong password";
} }
catch (Exception ex)
{
return ex.Message;
}
/*finally /*finally
{ {
// TODO: move this when implementing write mode // TODO: move this when implementing write mode

View File

@@ -39,7 +39,7 @@ namespace ModernKeePass
} }
} }
private async void openBbutton_Click(object sender, RoutedEventArgs e) private void openBbutton_Click(object sender, RoutedEventArgs e)
{ {
/*var database = DataContext as DatabaseVm; /*var database = DataContext as DatabaseVm;
database.Open(); database.Open();
@@ -47,7 +47,7 @@ namespace ModernKeePass
Frame.Navigate(typeof(GroupDetailPage), database.RootGroup);*/ Frame.Navigate(typeof(GroupDetailPage), database.RootGroup);*/
var homeVm = DataContext as HomeVm; var homeVm = DataContext as HomeVm;
var app = ((App)Application.Current); var app = ((App)Application.Current);
homeVm.ErrorMessage = await app.Database.Open(homeVm.Password); homeVm.ErrorMessage = app.Database.Open(homeVm.Password);
if (!app.Database.IsOpen) homeVm.NotifyPropertyChanged("ErrorMessage"); if (!app.Database.IsOpen) homeVm.NotifyPropertyChanged("ErrorMessage");
else Frame.Navigate(typeof(GroupDetailPage), app.Database.RootGroup); else Frame.Navigate(typeof(GroupDetailPage), app.Database.RootGroup);
} }

View File

@@ -159,8 +159,8 @@
</Page> </Page>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="ModernKeePassLib, Version=2.19.0.26255, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="ModernKeePassLib, Version=2.36.0.27373, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ModernKeePassLib.2.19.0.26255\lib\netstandard1.2\ModernKeePassLib.dll</HintPath> <HintPath>..\packages\ModernKeePassLib.2.36.0.27373\lib\netstandard1.2\ModernKeePassLib.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
@@ -221,7 +221,9 @@
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup> </PropertyGroup>
<Error Condition="!Exists('..\packages\NETStandard.Library.2.0.0\build\NETStandard.Library.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NETStandard.Library.2.0.0\build\NETStandard.Library.targets'))" /> <Error Condition="!Exists('..\packages\NETStandard.Library.2.0.0\build\NETStandard.Library.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NETStandard.Library.2.0.0\build\NETStandard.Library.targets'))" />
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets'))" />
</Target> </Target>
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">

View File

@@ -1,12 +1,5 @@
using System.ComponentModel; using System.ComponentModel;
using Windows.Storage;
using ModernKeePassLib;
using ModernKeePassLib.Keys;
using ModernKeePassLib.Serialization;
using ModernKeePassLib.Interfaces;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using System;
namespace ModernKeePass.ViewModels namespace ModernKeePass.ViewModels
{ {

View File

@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="win81" />
<package id="Microsoft.Bcl.Compression" version="3.9.85" targetFramework="win81" />
<package id="Microsoft.NETCore.Platforms" version="2.0.0" targetFramework="win81" /> <package id="Microsoft.NETCore.Platforms" version="2.0.0" targetFramework="win81" />
<package id="Microsoft.NETCore.Portable.Compatibility" version="1.0.2" targetFramework="win81" /> <package id="Microsoft.NETCore.Portable.Compatibility" version="1.0.2" targetFramework="win81" />
<package id="ModernKeePassLib" version="2.19.0.26255" targetFramework="win81" /> <package id="ModernKeePassLib" version="2.36.0.27373" targetFramework="win81" />
<package id="NETStandard.Library" version="2.0.0" targetFramework="win81" /> <package id="NETStandard.Library" version="2.0.0" targetFramework="win81" />
<package id="System.Net.Requests" version="4.3.0" targetFramework="win81" /> <package id="System.Net.Requests" version="4.3.0" targetFramework="win81" />
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="win81" /> <package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="win81" />

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -194,13 +194,6 @@ namespace ModernKeePassLib.Collections
return true; return true;
} }
public void Add(AutoTypeAssociation a)
{
Debug.Assert(a != null); if(a == null) throw new ArgumentNullException("a");
m_lWindowAssocs.Add(a);
}
public AutoTypeAssociation GetAt(int iIndex) public AutoTypeAssociation GetAt(int iIndex)
{ {
if((iIndex < 0) || (iIndex >= m_lWindowAssocs.Count)) if((iIndex < 0) || (iIndex >= m_lWindowAssocs.Count))
@@ -209,6 +202,22 @@ namespace ModernKeePassLib.Collections
return m_lWindowAssocs[iIndex]; return m_lWindowAssocs[iIndex];
} }
public void Add(AutoTypeAssociation a)
{
if(a == null) { Debug.Assert(false); throw new ArgumentNullException("a"); }
m_lWindowAssocs.Add(a);
}
public void Insert(int iIndex, AutoTypeAssociation a)
{
if((iIndex < 0) || (iIndex > m_lWindowAssocs.Count))
throw new ArgumentOutOfRangeException("iIndex");
if(a == null) { Debug.Assert(false); throw new ArgumentNullException("a"); }
m_lWindowAssocs.Insert(iIndex, a);
}
public void RemoveAt(int iIndex) public void RemoveAt(int iIndex)
{ {
if((iIndex < 0) || (iIndex >= m_lWindowAssocs.Count)) if((iIndex < 0) || (iIndex >= m_lWindowAssocs.Count))
@@ -216,5 +225,20 @@ namespace ModernKeePassLib.Collections
m_lWindowAssocs.RemoveAt(iIndex); m_lWindowAssocs.RemoveAt(iIndex);
} }
// public void Sort()
// {
// m_lWindowAssocs.Sort(AutoTypeConfig.AssocCompareFn);
// }
// private static int AssocCompareFn(AutoTypeAssociation x,
// AutoTypeAssociation y)
// {
// if(x == null) { Debug.Assert(false); return ((y == null) ? 0 : -1); }
// if(y == null) { Debug.Assert(false); return 1; }
// int cn = x.WindowName.CompareTo(y.WindowName);
// if(cn != 0) return cn;
// return x.Sequence.CompareTo(y.Sequence);
// }
} }
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@ using ModernKeePassLib.Security;
using ModernKeePassLib.Utility; using ModernKeePassLib.Utility;
#if KeePassLibSD #if KeePassLibSD
using ModernKeePassLibSD; using KeePassLibSD;
#endif #endif
namespace ModernKeePassLib.Collections namespace ModernKeePassLib.Collections

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@ using ModernKeePassLib.Security;
using ModernKeePassLib.Utility; using ModernKeePassLib.Utility;
#if KeePassLibSD #if KeePassLibSD
using ModernKeePassLibSD; using KeePassLibSD;
#endif #endif
namespace ModernKeePassLib.Collections namespace ModernKeePassLib.Collections

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -133,6 +133,14 @@ namespace ModernKeePassLib.Collections
} }
} }
public void Insert(uint uIndex, T pwObject)
{
Debug.Assert(pwObject != null);
if(pwObject == null) throw new ArgumentNullException("pwObject");
m_vObjects.Insert((int)uIndex, pwObject);
}
/// <summary> /// <summary>
/// Get an object of the list. /// Get an object of the list.
/// </summary> /// </summary>
@@ -225,7 +233,7 @@ namespace ModernKeePassLib.Collections
if(nCount <= 1) return; if(nCount <= 1) return;
int nIndex = m_vObjects.IndexOf(tObject); int nIndex = m_vObjects.IndexOf(tObject);
Debug.Assert(nIndex >= 0); if(nIndex < 0) { Debug.Assert(false); return; }
if(bUp && (nIndex > 0)) // No assert for top item if(bUp && (nIndex > 0)) // No assert for top item
{ {
@@ -241,6 +249,68 @@ namespace ModernKeePassLib.Collections
} }
} }
public void MoveOne(T[] vObjects, bool bUp)
{
Debug.Assert(vObjects != null);
if(vObjects == null) throw new ArgumentNullException("vObjects");
List<int> lIndices = new List<int>();
foreach(T t in vObjects)
{
if(t == null) { Debug.Assert(false); continue; }
int p = IndexOf(t);
if(p >= 0) lIndices.Add(p);
else { Debug.Assert(false); }
}
MoveOne(lIndices.ToArray(), bUp);
}
public void MoveOne(int[] vIndices, bool bUp)
{
Debug.Assert(vIndices != null);
if(vIndices == null) throw new ArgumentNullException("vIndices");
int n = m_vObjects.Count;
if(n <= 1) return; // No moving possible
int m = vIndices.Length;
if(m == 0) return; // Nothing to move
int[] v = new int[m];
Array.Copy(vIndices, v, m);
Array.Sort<int>(v);
if((bUp && (v[0] <= 0)) || (!bUp && (v[m - 1] >= (n - 1))))
return; // Moving as a block is not possible
int iStart = (bUp ? 0 : (m - 1));
int iExcl = (bUp ? m : -1);
int iStep = (bUp ? 1 : -1);
for(int i = iStart; i != iExcl; i += iStep)
{
int p = v[i];
if((p < 0) || (p >= n)) { Debug.Assert(false); continue; }
T t = m_vObjects[p];
if(bUp)
{
Debug.Assert(p > 0);
m_vObjects.RemoveAt(p);
m_vObjects.Insert(p - 1, t);
}
else // Down
{
Debug.Assert(p < (n - 1));
m_vObjects.RemoveAt(p);
m_vObjects.Insert(p + 1, t);
}
}
}
/// <summary> /// <summary>
/// Move some of the objects in this list to the top/bottom. /// Move some of the objects in this list to the top/bottom.
/// </summary> /// </summary>

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -26,15 +26,15 @@ using ModernKeePassLib.Delegates;
using ModernKeePassLib.Interfaces; using ModernKeePassLib.Interfaces;
#if KeePassLibSD #if KeePassLibSD
using ModernKeePassLibSD; using KeePassLibSD;
#endif #endif
namespace ModernKeePassLib.Collections namespace ModernKeePassLib.Collections
{ {
public sealed class PwObjectPool public sealed class PwObjectPool
{ {
private SortedDictionary<PwUuidComparable, IStructureItem> m_dict = private SortedDictionary<PwUuid, IStructureItem> m_dict =
new SortedDictionary<PwUuidComparable, IStructureItem>(); new SortedDictionary<PwUuid, IStructureItem>();
public static PwObjectPool FromGroupRecursive(PwGroup pgRoot, bool bEntries) public static PwObjectPool FromGroupRecursive(PwGroup pgRoot, bool bEntries)
{ {
@@ -42,16 +42,16 @@ namespace ModernKeePassLib.Collections
PwObjectPool p = new PwObjectPool(); PwObjectPool p = new PwObjectPool();
if(!bEntries) p.m_dict[new PwUuidComparable(pgRoot.Uuid)] = pgRoot; if(!bEntries) p.m_dict[pgRoot.Uuid] = pgRoot;
GroupHandler gh = delegate(PwGroup pg) GroupHandler gh = delegate(PwGroup pg)
{ {
p.m_dict[new PwUuidComparable(pg.Uuid)] = pg; p.m_dict[pg.Uuid] = pg;
return true; return true;
}; };
EntryHandler eh = delegate(PwEntry pe) EntryHandler eh = delegate(PwEntry pe)
{ {
p.m_dict[new PwUuidComparable(pe.Uuid)] = pe; p.m_dict[pe.Uuid] = pe;
return true; return true;
}; };
@@ -63,13 +63,13 @@ namespace ModernKeePassLib.Collections
public IStructureItem Get(PwUuid pwUuid) public IStructureItem Get(PwUuid pwUuid)
{ {
IStructureItem pItem; IStructureItem pItem;
m_dict.TryGetValue(new PwUuidComparable(pwUuid), out pItem); m_dict.TryGetValue(pwUuid, out pItem);
return pItem; return pItem;
} }
public bool ContainsOnlyType(Type t) public bool ContainsOnlyType(Type t)
{ {
foreach(KeyValuePair<PwUuidComparable, IStructureItem> kvp in m_dict) foreach(KeyValuePair<PwUuid, IStructureItem> kvp in m_dict)
{ {
if(kvp.Value.GetType() != t) return false; if(kvp.Value.GetType() != t) return false;
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -26,7 +26,7 @@ using System.Diagnostics;
using ModernKeePassLib.Interfaces; using ModernKeePassLib.Interfaces;
#if KeePassLibSD #if KeePassLibSD
using ModernKeePassLibSD; using KeePassLibSD;
#endif #endif
namespace ModernKeePassLib.Collections namespace ModernKeePassLib.Collections

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -19,13 +19,17 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Security;
namespace ModernKeePassLib.Cryptography.Cipher namespace ModernKeePassLib.Cryptography.Cipher
{ {
/// <summary> /// <summary>
/// Pool of encryption/decryption algorithms (ciphers). /// Pool of encryption/decryption algorithms (ciphers).
/// </summary> /// </summary>
public sealed class CipherPool public sealed class CipherPool
{ {
private List<ICipherEngine> m_vCiphers = new List<ICipherEngine>(); private List<ICipherEngine> m_vCiphers = new List<ICipherEngine>();
private static CipherPool m_poolGlobal = null; private static CipherPool m_poolGlobal = null;
@@ -65,7 +69,7 @@ namespace ModernKeePassLib.Cryptography.Cipher
// Return if a cipher with that ID is registered already. // Return if a cipher with that ID is registered already.
for(int i = 0; i < m_vCiphers.Count; ++i) for(int i = 0; i < m_vCiphers.Count; ++i)
if(m_vCiphers[i].CipherUuid.EqualsValue(csEngine.CipherUuid)) if(m_vCiphers[i].CipherUuid.Equals(csEngine.CipherUuid))
return; return;
m_vCiphers.Add(csEngine); m_vCiphers.Add(csEngine);
@@ -81,7 +85,7 @@ namespace ModernKeePassLib.Cryptography.Cipher
{ {
foreach(ICipherEngine iEngine in m_vCiphers) foreach(ICipherEngine iEngine in m_vCiphers)
{ {
if(iEngine.CipherUuid.EqualsValue(uuidCipher)) if(iEngine.CipherUuid.Equals(uuidCipher))
return iEngine; return iEngine;
} }
@@ -99,7 +103,7 @@ namespace ModernKeePassLib.Cryptography.Cipher
{ {
for(int i = 0; i < m_vCiphers.Count; ++i) for(int i = 0; i < m_vCiphers.Count; ++i)
{ {
if(m_vCiphers[i].CipherUuid.EqualsValue(uuidCipher)) if(m_vCiphers[i].CipherUuid.Equals(uuidCipher))
return i; return i;
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -26,7 +26,7 @@ using ModernKeePassLib.Utility;
namespace ModernKeePassLib.Cryptography.Cipher namespace ModernKeePassLib.Cryptography.Cipher
{ {
public sealed class Salsa20Cipher public sealed class Salsa20Cipher : IDisposable
{ {
private uint[] m_state = new uint[16]; private uint[] m_state = new uint[16];
private uint[] m_x = new uint[16]; // Working buffer private uint[] m_x = new uint[16]; // Working buffer
@@ -34,7 +34,7 @@ namespace ModernKeePassLib.Cryptography.Cipher
private byte[] m_output = new byte[64]; private byte[] m_output = new byte[64];
private int m_outputPos = 64; private int m_outputPos = 64;
private static readonly uint[] m_sigma = new uint[4]{ private static readonly uint[] m_sigma = new uint[4] {
0x61707865, 0x3320646E, 0x79622D32, 0x6B206574 0x61707865, 0x3320646E, 0x79622D32, 0x6B206574
}; };
@@ -45,6 +45,17 @@ namespace ModernKeePassLib.Cryptography.Cipher
} }
~Salsa20Cipher() ~Salsa20Cipher()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool bDisposing)
{ {
// Clear sensitive data // Clear sensitive data
Array.Clear(m_state, 0, m_state.Length); Array.Clear(m_state, 0, m_state.Length);

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -17,22 +17,44 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
using System; using System;
using System.Collections.Generic;
using System.Text;
using System.IO; using System.IO;
using System.Security;
using System.Diagnostics;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Security.Cryptography.Core;
#if PCL
using Windows.Security.Cryptography;
#else
#if !KeePassRT
using System.Security.Cryptography;
#else
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.IO;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters;
#endif
#endif
using ModernKeePassLib.Resources; using ModernKeePassLib.Resources;
using ModernKeePassLib.Serialization;
namespace ModernKeePassLib.Cryptography.Cipher namespace ModernKeePassLib.Cryptography.Cipher
{ {
/// <summary> /// <summary>
/// Standard AES cipher implementation. /// Standard AES cipher implementation.
/// </summary> /// </summary>
public sealed class StandardAesEngine : ICipherEngine public sealed class StandardAesEngine : ICipherEngine
{ {
// private const CipherMode m_rCipherMode = CipherMode.CBC; #if !PCL && !KeePassRT
// private const PaddingMode m_rCipherPadding = PaddingMode.PKCS7; private const CipherMode m_rCipherMode = CipherMode.CBC;
private const PaddingMode m_rCipherPadding = PaddingMode.PKCS7;
#endif
private static PwUuid m_uuidAes = null; private static PwUuid m_uuidAes = null;
@@ -92,31 +114,41 @@ namespace ModernKeePassLib.Cryptography.Cipher
} }
} }
private static Stream CreateStream(Stream s, bool bEncrypt, byte[] pbKey, byte[] pbIV) private static Stream CreateStream(Stream s, bool bEncrypt, byte[] pbKey, byte[] pbIV)
{ {
StandardAesEngine.ValidateArguments(s, bEncrypt, pbKey, pbIV); ValidateArguments(s, bEncrypt, pbKey, pbIV);
return new CryptoStream( s, "AES_CBC_PKCS7", bEncrypt, pbKey, pbIV); #if PCL
var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
var key = provider.CreateSymmetricKey(CryptographicBuffer.GenerateRandom(32));
using (var ms = new MemoryStream())
{
s.CopyTo(ms);
if (bEncrypt)
{
return CryptographicEngine.Encrypt(key, ms.GetWindowsRuntimeBuffer(), CryptographicBuffer.GenerateRandom(16)).AsStream();
}
/*var encryptor = CryptographicEngine.CreateEncryptor(
key, pbLocalIV);
return new CryptoStream(s, encryptor, CryptoStreamMode.Write);*/
} return CryptographicEngine.Decrypt(key, ms.GetWindowsRuntimeBuffer(), CryptographicBuffer.GenerateRandom(16)).AsStream();
#if false /*var decryptor = CryptographicEngine.CreateDecryptor(
key, pbLocalIV);
return new CryptoStream(s, decryptor, CryptoStreamMode.Read);*/
}
#else
#if !KeePassRT
RijndaelManaged r = new RijndaelManaged(); RijndaelManaged r = new RijndaelManaged();
if(r.BlockSize != 128) // AES block size if(r.BlockSize != 128) // AES block size
{ {
Debug.Assert(false); Debug.Assert(false);
r.BlockSize = 128; r.BlockSize = 128;
} }
byte[] pbLocalIV = new byte[16];
Array.Copy(pbIV, pbLocalIV, 16);
r.IV = pbLocalIV; r.IV = pbLocalIV;
byte[] pbLocalKey = new byte[32];
Array.Copy(pbKey, pbLocalKey, 32);
r.KeySize = 256; r.KeySize = 256;
r.Key = pbLocalKey; r.Key = pbLocalKey;
r.Mode = m_rCipherMode; r.Mode = m_rCipherMode;
r.Padding = m_rCipherPadding; r.Padding = m_rCipherPadding;
@@ -126,11 +158,24 @@ namespace ModernKeePassLib.Cryptography.Cipher
return new CryptoStream(s, iTransform, bEncrypt ? CryptoStreamMode.Write : return new CryptoStream(s, iTransform, bEncrypt ? CryptoStreamMode.Write :
CryptoStreamMode.Read); CryptoStreamMode.Read);
} #else
AesEngine aes = new AesEngine();
CbcBlockCipher cbc = new CbcBlockCipher(aes);
PaddedBufferedBlockCipher bc = new PaddedBufferedBlockCipher(cbc,
new Pkcs7Padding());
KeyParameter kp = new KeyParameter(pbLocalKey);
ParametersWithIV prmIV = new ParametersWithIV(kp, pbLocalIV);
bc.Init(bEncrypt, prmIV);
IBufferedCipher cpRead = (bEncrypt ? null : bc);
IBufferedCipher cpWrite = (bEncrypt ? bc : null);
return new CipherStream(s, cpRead, cpWrite);
#endif #endif
#endif
}
public Stream EncryptStream(Stream sPlainText, byte[] pbKey, byte[] pbIV) public Stream EncryptStream(Stream sPlainText, byte[] pbKey, byte[] pbIV)
{ {
return StandardAesEngine.CreateStream(sPlainText, true, pbKey, pbIV); return StandardAesEngine.CreateStream(sPlainText, true, pbKey, pbIV);
} }
@@ -139,7 +184,5 @@ namespace ModernKeePassLib.Cryptography.Cipher
{ {
return StandardAesEngine.CreateStream(sEncrypted, false, pbKey, pbIV); return StandardAesEngine.CreateStream(sEncrypted, false, pbKey, pbIV);
} }
}
}
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -18,26 +18,37 @@
*/ */
using System; using System;
using System.Security;
#if PCL
using Windows.Security.Cryptography; using Windows.Security.Cryptography;
//using System.Windows.Forms; #else
//using System.Drawing; using System.Security.Cryptography;
#endif
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Security.Cryptography.Core;
using ModernKeePassLib.Utility;
namespace ModernKeePassLib.Cryptography namespace ModernKeePassLib.Cryptography
{ {
/// <summary> /// <summary>
/// Cryptographically strong random number generator. The returned values /// Cryptographically strong random number generator. The returned values
/// are unpredictable and cannot be reproduced. /// are unpredictable and cannot be reproduced.
/// <c>CryptoRandom</c> is a singleton class. /// <c>CryptoRandom</c> is a singleton class.
/// </summary> /// </summary>
public sealed class CryptoRandom public sealed class CryptoRandom
{ {
//private byte[] m_pbEntropyPool = new byte[64]; private byte[] m_pbEntropyPool = new byte[64];
//private uint m_uCounter; private uint m_uCounter;
//private RNGCryptoServiceProvider m_rng = new RNGCryptoServiceProvider(); #if PCL
//private ulong m_uGeneratedBytesCount = 0; //private IRandomNumberGenerator m_rng = NetFxCrypto.RandomNumberGenerator;
#else
private RNGCryptoServiceProvider m_rng = new RNGCryptoServiceProvider();
#endif
private ulong m_uGeneratedBytesCount = 0;
// private object m_oSyncRoot = new object(); private object m_oSyncRoot = new object();
private static CryptoRandom m_pInstance = null; private static CryptoRandom m_pInstance = null;
public static CryptoRandom Instance public static CryptoRandom Instance
@@ -51,44 +62,7 @@ namespace ModernKeePassLib.Cryptography
} }
} }
#if KeePassWinRT
private CryptoRandom()
{
}
/// <summary>
/// Update the internal seed of the random number generator based
/// on entropy data.
/// This method is thread-safe.
/// </summary>
/// <param name="pbEntropy">Entropy bytes.</param>
public void AddEntropy(byte[] pbEntropy)
{
// Not used in WinRT version
}
/// <summary> /// <summary>
/// Get a number of cryptographically strong random bytes.
/// This method is thread-safe.
/// </summary>
/// <param name="uRequestedBytes">Number of requested random bytes.</param>
/// <returns>A byte array consisting of <paramref name="uRequestedBytes" />
/// random bytes.</returns>
public byte[] GetRandomBytes(uint uRequestedBytes)
{
if (uRequestedBytes == 0) return new byte[0]; // Allow zero-length array
byte[] pbRes;
Windows.Storage.Streams.IBuffer buffer = CryptographicBuffer.GenerateRandom(uRequestedBytes);
CryptographicBuffer.CopyToByteArray(buffer, out pbRes);
return pbRes;
}
#else
/// <summary>
/// Get the number of random bytes that this instance generated so far. /// Get the number of random bytes that this instance generated so far.
/// Note that this number can be higher than the number of random bytes /// Note that this number can be higher than the number of random bytes
/// actually requested using the <c>GetRandomBytes</c> method. /// actually requested using the <c>GetRandomBytes</c> method.
@@ -126,19 +100,25 @@ namespace ModernKeePassLib.Cryptography
/// <param name="pbEntropy">Entropy bytes.</param> /// <param name="pbEntropy">Entropy bytes.</param>
public void AddEntropy(byte[] pbEntropy) public void AddEntropy(byte[] pbEntropy)
{ {
if(pbEntropy == null) { Debug.Assert(false); return; } if(pbEntropy == null) { Debug.Assert(false); return; }
if(pbEntropy.Length == 0) { Debug.Assert(false); return; } if(pbEntropy.Length == 0) { Debug.Assert(false); return; }
byte[] pbNewData = pbEntropy; byte[] pbNewData = pbEntropy;
if(pbEntropy.Length >= 64) if(pbEntropy.Length >= 64)
{ {
#if PCL
var shaNew = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha512);
pbNewData = shaNew.HashData(pbEntropy.AsBuffer()).ToArray();
#else
#if !KeePassLibSD #if !KeePassLibSD
SHA512Managed shaNew = new SHA512Managed(); SHA512Managed shaNew = new SHA512Managed();
#else #else
SHA256Managed shaNew = new SHA256Managed(); SHA256Managed shaNew = new SHA256Managed();
#endif #endif
pbNewData = shaNew.ComputeHash(pbEntropy); pbNewData = shaNew.ComputeHash(pbEntropy);
#endif
} }
MemoryStream ms = new MemoryStream(); MemoryStream ms = new MemoryStream();
@@ -148,6 +128,11 @@ namespace ModernKeePassLib.Cryptography
ms.Write(pbNewData, 0, pbNewData.Length); ms.Write(pbNewData, 0, pbNewData.Length);
byte[] pbFinal = ms.ToArray(); byte[] pbFinal = ms.ToArray();
#if PCL
var shaPool = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha512);
m_pbEntropyPool = shaPool.HashData(pbFinal.AsBuffer()).ToArray();
#else
#if !KeePassLibSD #if !KeePassLibSD
Debug.Assert(pbFinal.Length == (64 + pbNewData.Length)); Debug.Assert(pbFinal.Length == (64 + pbNewData.Length));
SHA512Managed shaPool = new SHA512Managed(); SHA512Managed shaPool = new SHA512Managed();
@@ -155,16 +140,14 @@ namespace ModernKeePassLib.Cryptography
SHA256Managed shaPool = new SHA256Managed(); SHA256Managed shaPool = new SHA256Managed();
#endif #endif
m_pbEntropyPool = shaPool.ComputeHash(pbFinal); m_pbEntropyPool = shaPool.ComputeHash(pbFinal);
#endif
} }
ms.Close(); ms.Dispose();
} }
private static byte[] GetSystemData(Random rWeak) private static byte[] GetSystemData(Random rWeak)
{ {
MemoryStream ms = new MemoryStream(); MemoryStream ms = new MemoryStream();
byte[] pb; byte[] pb;
@@ -174,21 +157,36 @@ namespace ModernKeePassLib.Cryptography
pb = TimeUtil.PackTime(DateTime.Now); pb = TimeUtil.PackTime(DateTime.Now);
ms.Write(pb, 0, pb.Length); ms.Write(pb, 0, pb.Length);
#if !KeePassLibSD #if (!PCL && !KeePassLibSD && !KeePassRT)
Point pt = Cursor.Position; // In try-catch for systems without GUI;
pb = MemUtil.UInt32ToBytes((uint)pt.X); // https://sourceforge.net/p/keepass/discussion/329221/thread/20335b73/
ms.Write(pb, 0, pb.Length); try
pb = MemUtil.UInt32ToBytes((uint)pt.Y); {
ms.Write(pb, 0, pb.Length); Point pt = Cursor.Position;
pb = MemUtil.UInt32ToBytes((uint)pt.X);
ms.Write(pb, 0, pb.Length);
pb = MemUtil.UInt32ToBytes((uint)pt.Y);
ms.Write(pb, 0, pb.Length);
}
catch(Exception) { }
#endif #endif
pb = MemUtil.UInt32ToBytes((uint)rWeak.Next()); pb = MemUtil.UInt32ToBytes((uint)rWeak.Next());
ms.Write(pb, 0, pb.Length); ms.Write(pb, 0, pb.Length);
pb = MemUtil.UInt32ToBytes((uint)NativeLib.GetPlatformID()); #if PCL
pb = MemUtil.UInt32ToBytes((uint)Environment.ProcessorCount);
ms.Write(pb, 0, pb.Length); ms.Write(pb, 0, pb.Length);
#if !KeePassLibSD pb = MemUtil.UInt32ToBytes((uint)Environment.CurrentManagedThreadId);
ms.Write(pb, 0, pb.Length);
#else
pb = MemUtil.UInt32ToBytes((uint)NativeLib.GetPlatformID());
ms.Write(pb, 0, pb.Length);
#endif
#if (!PCL && !KeePassLibSD && !KeePassRT)
Process p = null;
try try
{ {
pb = MemUtil.UInt32ToBytes((uint)Environment.ProcessorCount); pb = MemUtil.UInt32ToBytes((uint)Environment.ProcessorCount);
@@ -197,13 +195,11 @@ namespace ModernKeePassLib.Cryptography
ms.Write(pb, 0, pb.Length); ms.Write(pb, 0, pb.Length);
Version v = Environment.OSVersion.Version; Version v = Environment.OSVersion.Version;
int nv = (v.Major << 28) + (v.MajorRevision << 24) + pb = MemUtil.UInt32ToBytes((uint)v.GetHashCode());
(v.Minor << 20) + (v.MinorRevision << 16) +
(v.Revision << 12) + v.Build;
pb = MemUtil.UInt32ToBytes((uint)nv);
ms.Write(pb, 0, pb.Length); ms.Write(pb, 0, pb.Length);
Process p = Process.GetCurrentProcess(); p = Process.GetCurrentProcess();
pb = MemUtil.UInt64ToBytes((ulong)p.Handle.ToInt64()); pb = MemUtil.UInt64ToBytes((ulong)p.Handle.ToInt64());
ms.Write(pb, 0, pb.Length); ms.Write(pb, 0, pb.Length);
pb = MemUtil.UInt32ToBytes((uint)p.HandleCount); pb = MemUtil.UInt32ToBytes((uint)p.HandleCount);
@@ -236,33 +232,31 @@ namespace ModernKeePassLib.Cryptography
// ms.Write(pb, 0, pb.Length); // ms.Write(pb, 0, pb.Length);
} }
catch(Exception) { } catch(Exception) { }
finally
{
try { if(p != null) p.Dispose(); }
catch(Exception) { Debug.Assert(false); }
}
#endif #endif
pb = Guid.NewGuid().ToByteArray(); pb = Guid.NewGuid().ToByteArray();
ms.Write(pb, 0, pb.Length); ms.Write(pb, 0, pb.Length);
byte[] pbAll = ms.ToArray(); byte[] pbAll = ms.ToArray();
ms.Close(); ms.Dispose();
return pbAll; return pbAll;
} }
private byte[] GetCspData() private byte[] GetCspData()
{ {
uint length = 32; //byte[] pbCspRandom = new byte[32];
byte[] pbCspRandom = new byte[length]; var pbCspRandom = CryptographicBuffer.GenerateRandom(32);
Windows.Storage.Streams.IBuffer buffer = CryptographicBuffer.GenerateRandom(length);
CryptographicBuffer.CopyToByteArray(buffer, pbCspRandom);
//m_rng.GetBytes(pbCspRandom); //m_rng.GetBytes(pbCspRandom);
return pbCspRandom; return pbCspRandom.ToArray();
} }
private byte[] GenerateRandom256() private byte[] GenerateRandom256()
{ {
if(this.GenerateRandom256Pre != null) if(this.GenerateRandom256Pre != null)
this.GenerateRandom256Pre(this, EventArgs.Empty); this.GenerateRandom256Pre(this, EventArgs.Empty);
@@ -281,16 +275,20 @@ namespace ModernKeePassLib.Cryptography
pbFinal = ms.ToArray(); pbFinal = ms.ToArray();
Debug.Assert(pbFinal.Length == (m_pbEntropyPool.Length + Debug.Assert(pbFinal.Length == (m_pbEntropyPool.Length +
pbCounter.Length + pbCspRandom.Length)); pbCounter.Length + pbCspRandom.Length));
ms.Close(); ms.Dispose();
m_uGeneratedBytesCount += 32; m_uGeneratedBytesCount += 32;
} }
#if PCL
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
return sha256.HashData(pbFinal.AsBuffer()).ToArray();
#else
SHA256Managed sha256 = new SHA256Managed(); SHA256Managed sha256 = new SHA256Managed();
return sha256.ComputeHash(pbFinal); return sha256.ComputeHash(pbFinal);
#endif
} }
/// <summary> /// <summary>
/// Get a number of cryptographically strong random bytes. /// Get a number of cryptographically strong random bytes.
/// This method is thread-safe. /// This method is thread-safe.
@@ -312,7 +310,7 @@ namespace ModernKeePassLib.Cryptography
long lCopy = (long)((uRequestedBytes < 32) ? uRequestedBytes : 32); long lCopy = (long)((uRequestedBytes < 32) ? uRequestedBytes : 32);
#if !KeePassLibSD #if (!PCL && !KeePassLibSD && !KeePassRT)
Array.Copy(pbRandom256, 0, pbRes, lPos, lCopy); Array.Copy(pbRandom256, 0, pbRes, lPos, lCopy);
#else #else
Array.Copy(pbRandom256, 0, pbRes, (int)lPos, (int)lCopy); Array.Copy(pbRandom256, 0, pbRes, (int)lPos, (int)lCopy);
@@ -325,8 +323,5 @@ namespace ModernKeePassLib.Cryptography
Debug.Assert((int)lPos == pbRes.Length); Debug.Assert((int)lPos == pbRes.Length);
return pbRes; return pbRes;
} }
#endif // !KeePassWinRT
} }
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -18,15 +18,23 @@
*/ */
using System; using System;
using System.Diagnostics;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Security.Cryptography.Core;
#if PCL
using Windows.Security.Cryptography;
#else
using System.Security.Cryptography;
#endif
using ModernKeePassLib.Cryptography.Cipher; using ModernKeePassLib.Cryptography.Cipher;
namespace ModernKeePassLib.Cryptography namespace ModernKeePassLib.Cryptography
{ {
/// <summary> /// <summary>
/// Algorithms supported by <c>CryptoRandomStream</c>. /// Algorithms supported by <c>CryptoRandomStream</c>.
/// </summary> /// </summary>
public enum CrsAlgorithm public enum CrsAlgorithm
{ {
/// <summary> /// <summary>
/// Not supported. /// Not supported.
@@ -109,13 +117,17 @@ namespace ModernKeePassLib.Cryptography
} }
else if(genAlgorithm == CrsAlgorithm.Salsa20) else if(genAlgorithm == CrsAlgorithm.Salsa20)
{ {
byte[] pbKey32 = SHA256Managed.Instance.ComputeHash(pbKey); #if PCL
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
byte[] pbIV = new byte[]{ 0xE8, 0x30, 0x09, 0x4B, var pbKey32 = sha256.HashData(pbKey.AsBuffer()).ToArray();
#else
SHA256Managed sha256 = new SHA256Managed();
byte[] pbKey32 = sha256.ComputeHash(pbKey);
#endif
byte[] pbIV = new byte[8] { 0xE8, 0x30, 0x09, 0x4B,
0x97, 0x20, 0x5D, 0x2A }; // Unique constant 0x97, 0x20, 0x5D, 0x2A }; // Unique constant
m_salsa20 = new Salsa20Cipher(pbKey32, pbIV); m_salsa20 = new Salsa20Cipher(pbKey32, pbIV);
} }
else // Unknown algorithm else // Unknown algorithm
{ {

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -17,85 +17,80 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
using ModernKeePassLib.Utility;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
using System.IO; using System.IO;
#if PCL
using Windows.Security.Cryptography; using Windows.Security.Cryptography;
#else
using System.Security.Cryptography;
#endif
using System.Diagnostics;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Security.Cryptography.Core; using Windows.Security.Cryptography.Core;
using ModernKeePassLib.Utility;
using CryptographicHash = Windows.Security.Cryptography.Core.CryptographicHash;
namespace ModernKeePassLib.Cryptography namespace ModernKeePassLib.Cryptography
{ {
public sealed class HashingStreamEx : Stream public sealed class HashingStreamEx : Stream
{ {
private Stream m_sBaseStream; private Stream m_sBaseStream;
private bool m_bWriting; private bool m_bWriting;
private Queue<byte[]> m_DataToHash; #if PCL
//private HashAlgorithm m_hash; private CryptographicHash m_hash;
public byte[] Hash
{
get
{
int len = 0;
foreach (byte[] block in m_DataToHash)
{
len += block.Length;
}
byte[] dataToHash = new byte[len];
int pos = 0;
while(m_DataToHash.Count > 0)
{
byte[] block = m_DataToHash.Dequeue();
Array.Copy(block, 0, dataToHash, pos, block.Length);
pos += block.Length;
}
byte[] hash = SHA256Managed.Instance.ComputeHash(dataToHash);
return hash;
}
}
public override bool CanRead
{
get { return !m_bWriting; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return m_bWriting; }
}
public override long Length
{
get { return m_sBaseStream.Length; }
}
public override long Position
{
get { return m_sBaseStream.Position; }
set { throw new NotSupportedException(); }
}
public HashingStreamEx(Stream sBaseStream, bool bWriting, CryptographicHash hashAlgorithm)
{
if (sBaseStream == null) throw new ArgumentNullException("sBaseStream");
m_sBaseStream = sBaseStream;
m_bWriting = bWriting;
#if KeePassWinRT
m_DataToHash = new Queue<byte[]>();
#else #else
#if !KeePassLibSD private HashAlgorithm m_hash;
#endif
private byte[] m_pbFinalHash = null;
public byte[] Hash
{
get { return m_pbFinalHash; }
}
public override bool CanRead
{
get { return !m_bWriting; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return m_bWriting; }
}
public override long Length
{
get { return m_sBaseStream.Length; }
}
public override long Position
{
get { return m_sBaseStream.Position; }
set { throw new NotSupportedException(); }
}
#if PCL
public HashingStreamEx(Stream sBaseStream, bool bWriting, string hashAlgorithm)
#else
public HashingStreamEx(Stream sBaseStream, bool bWriting, HashAlgorithm hashAlgorithm)
#endif
{
if(sBaseStream == null)
throw new ArgumentNullException("sBaseStream");
m_sBaseStream = sBaseStream;
m_bWriting = bWriting;
#if PCL
m_hash = HashAlgorithmProvider.OpenAlgorithm(hashAlgorithm ?? HashAlgorithmNames.Sha256).CreateHash();
#elif !KeePassLibSD
m_hash = (hashAlgorithm ?? new SHA256Managed()); m_hash = (hashAlgorithm ?? new SHA256Managed());
#else // KeePassLibSD #else // KeePassLibSD
m_hash = null; m_hash = null;
@@ -105,91 +100,98 @@ namespace ModernKeePassLib.Cryptography
try { if(m_hash == null) m_hash = HashAlgorithm.Create(); } try { if(m_hash == null) m_hash = HashAlgorithm.Create(); }
catch(Exception) { } catch(Exception) { }
#endif #endif
#endif // KeePassWinRT if(m_hash == null) { Debug.Assert(false); return; }
#if TODO
// Bert TODO: For the time being, only built-in Hash algorithm are supported.
if (m_hash == null) { Debug.Assert(false); return; }
// Validate hash algorithm // Validate hash algorithm
if((!m_hash.CanReuseTransform) || (!m_hash.CanTransformMultipleBlocks) || /*if((!m_hash.CanReuseTransform) || (!m_hash.CanTransformMultipleBlocks) ||
(m_hash.InputBlockSize != 1) || (m_hash.OutputBlockSize != 1)) (m_hash.InputBlockSize != 1) || (m_hash.OutputBlockSize != 1))
{ {
#if DEBUG #if false && DEBUG
MessageService.ShowWarning("Broken HashAlgorithm object in HashingStreamEx."); MessageService.ShowWarning("Broken HashAlgorithm object in HashingStreamEx.");
#endif #endif
m_hash = null; m_hash = null;
} }*/
#endif }
}
public override void Flush() public override void Flush()
{
m_sBaseStream.Flush();
}
/*public override void Close()
{ {
m_sBaseStream.Flush();
}
#if PCL || KeePassRT
protected override void Dispose(bool disposing)
{
if(!disposing) return;
#else
public override void Close()
{
#endif
if(m_hash != null) if(m_hash != null)
{ {
try try
{ {
m_hash.TransformFinalBlock(new byte[0], 0, 0); //m_hash.TransformFinalBlock(new byte[0], 0, 0);
#if PCL
m_pbFinalHash = m_hash.GetValueAndReset().ToArray();
#else
m_pbFinalHash = m_hash.Hash; m_pbFinalHash = m_hash.Hash;
#endif
} }
catch(Exception) { Debug.Assert(false); } catch(Exception) { Debug.Assert(false); }
m_hash = null; m_hash = null;
} }
m_sBaseStream.Close(); m_sBaseStream.Dispose();
}
}*/ public override long Seek(long lOffset, SeekOrigin soOrigin)
{
throw new NotSupportedException();
}
public override long Seek(long lOffset, SeekOrigin soOrigin) public override void SetLength(long lValue)
{ {
throw new NotSupportedException(); throw new NotSupportedException();
} }
public override void SetLength(long lValue) public override int Read(byte[] pbBuffer, int nOffset, int nCount)
{ {
throw new NotSupportedException(); if(m_bWriting) throw new InvalidOperationException();
}
public override int Read(byte[] pbBuffer, int nOffset, int nCount) int nRead = m_sBaseStream.Read(pbBuffer, nOffset, nCount);
{ int nPartialRead = nRead;
while((nRead < nCount) && (nPartialRead != 0))
{
nPartialRead = m_sBaseStream.Read(pbBuffer, nOffset + nRead,
nCount - nRead);
nRead += nPartialRead;
}
if (m_bWriting) throw new InvalidOperationException(); #if DEBUG
byte[] pbOrg = new byte[pbBuffer.Length];
Array.Copy(pbBuffer, pbOrg, pbBuffer.Length);
#endif
int nRead = m_sBaseStream.Read(pbBuffer, nOffset, nCount); /*if((m_hash != null) && (nRead > 0))
m_hash.TransformBlock(pbBuffer, nOffset, nRead, pbBuffer, nOffset);*/
// Mono bug workaround (LaunchPad 798910) #if DEBUG
int nPartialRead = nRead; Debug.Assert(MemUtil.ArraysEqual(pbBuffer, pbOrg));
while ((nRead < nCount) && (nPartialRead != 0)) #endif
{
nPartialRead = m_sBaseStream.Read(pbBuffer, nOffset + nRead,
nCount - nRead);
nRead += nPartialRead;
}
byte[] pbOrg = new byte[nRead]; return nRead;
Array.Copy(pbBuffer, pbOrg, nRead); }
m_DataToHash.Enqueue(pbOrg);
return nRead; public override void Write(byte[] pbBuffer, int nOffset, int nCount)
} {
public override void Write(byte[] pbBuffer, int nOffset, int nCount)
{
if(!m_bWriting) throw new InvalidOperationException(); if(!m_bWriting) throw new InvalidOperationException();
#if DEBUG #if DEBUG
byte[] pbOrg = new byte[pbBuffer.Length]; byte[] pbOrg = new byte[pbBuffer.Length];
Array.Copy(pbBuffer, pbOrg, pbBuffer.Length); Array.Copy(pbBuffer, pbOrg, pbBuffer.Length);
#endif #endif
// TODO: implement this
/*if((m_hash != null) && (nCount > 0)) /*if((m_hash != null) && (nCount > 0))
m_hash.TransformBlock(pbBuffer, nOffset, nCount, pbBuffer, nOffset);*/ m_hash.TransformBlock(pbBuffer, nOffset, nCount, pbBuffer, nOffset);*/
@@ -198,7 +200,6 @@ namespace ModernKeePassLib.Cryptography
#endif #endif
m_sBaseStream.Write(pbBuffer, nOffset, nCount); m_sBaseStream.Write(pbBuffer, nOffset, nCount);
}
} }
}
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -17,15 +17,23 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
using System;
#if PCL
using Windows.Security.Cryptography.Core;
#else
using System.Security.Cryptography;
#endif
using System.Globalization;
using System.Runtime.InteropServices.WindowsRuntime;
using ModernKeePassLib.Utility;
#if (!KeePassLibSD && !KeePassRT)
#if !KeePassLibSD
namespace ModernKeePassLib.Cryptography namespace ModernKeePassLib.Cryptography
{ {
/// <summary> /// <summary>
/// Generate HMAC-based one-time passwords as specified in RFC 4226. /// Generate HMAC-based one-time passwords as specified in RFC 4226.
/// </summary> /// </summary>
public static class HmacOtp public static class HmacOtp
{ {
private static readonly uint[] vDigitsPower = new uint[]{ 1, 10, 100, private static readonly uint[] vDigitsPower = new uint[]{ 1, 10, 100,
1000, 10000, 100000, 1000000, 10000000, 100000000 }; 1000, 10000, 100000, 1000000, 10000000, 100000000 };
@@ -33,14 +41,17 @@ namespace ModernKeePassLib.Cryptography
public static string Generate(byte[] pbSecret, ulong uFactor, public static string Generate(byte[] pbSecret, ulong uFactor,
uint uCodeDigits, bool bAddChecksum, int iTruncationOffset) uint uCodeDigits, bool bAddChecksum, int iTruncationOffset)
{ {
Debug.Assert(false, "Not yet implemented");
return null;
#if TODO
byte[] pbText = MemUtil.UInt64ToBytes(uFactor); byte[] pbText = MemUtil.UInt64ToBytes(uFactor);
Array.Reverse(pbText); // Big-Endian Array.Reverse(pbText); // Big-Endian
#if PCL
var hsha1 = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha1).CreateHash(pbSecret.AsBuffer());
hsha1.Append(pbText.AsBuffer());
var pbHash = hsha1.GetValueAndReset().ToArray();
#else
HMACSHA1 hsha1 = new HMACSHA1(pbSecret); HMACSHA1 hsha1 = new HMACSHA1(pbSecret);
byte[] pbHash = hsha1.ComputeHash(pbText); byte[] pbHash = hsha1.ComputeHash(pbText);
#endif
uint uOffset = (uint)(pbHash[pbHash.Length - 1] & 0xF); uint uOffset = (uint)(pbHash[pbHash.Length - 1] & 0xF);
if((iTruncationOffset >= 0) && (iTruncationOffset < (pbHash.Length - 4))) if((iTruncationOffset >= 0) && (iTruncationOffset < (pbHash.Length - 4)))
@@ -56,8 +67,8 @@ namespace ModernKeePassLib.Cryptography
uOtp = ((uOtp * 10) + CalculateChecksum(uOtp, uCodeDigits)); uOtp = ((uOtp * 10) + CalculateChecksum(uOtp, uCodeDigits));
uint uDigits = (bAddChecksum ? (uCodeDigits + 1) : uCodeDigits); uint uDigits = (bAddChecksum ? (uCodeDigits + 1) : uCodeDigits);
return uOtp.ToString().PadLeft((int)uDigits, '0'); return uOtp.ToString(NumberFormatInfo.InvariantInfo).PadLeft(
#endif (int)uDigits, '0');
} }
private static readonly uint[] vDoubleDigits = new uint[]{ 0, 2, 4, 6, 8, private static readonly uint[] vDoubleDigits = new uint[]{ 0, 2, 4, 6, 8,

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -66,7 +66,7 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
foreach(CustomPwGenerator pwg in m_vGens) foreach(CustomPwGenerator pwg in m_vGens)
{ {
if(uuid.EqualsValue(pwg.Uuid)) return pwg; if(uuid.Equals(pwg.Uuid)) return pwg;
} }
return null; return null;
@@ -90,7 +90,7 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
for(int i = 0; i < m_vGens.Count; ++i) for(int i = 0; i < m_vGens.Count; ++i)
{ {
if(uuid.EqualsValue(m_vGens[i].Uuid)) return i; if(uuid.Equals(m_vGens[i].Uuid)) return i;
} }
return -1; return -1;

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -67,6 +67,17 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
pcsUsed.Add(ch); pcsUsed.Add(ch);
} }
} }
else if(ch == '^')
{
ch = csStream.ReadChar();
if(ch == char.MinValue) // ^ at the end
{
vGenerated.AddLast('^');
break;
}
if(bInCharSetDef) pcsCustom.Remove(ch);
}
else if(ch == '[') else if(ch == '[')
{ {
pcsCustom.Clear(); pcsCustom.Clear();

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -46,51 +46,87 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
public const string Invalid = "\t\r\n"; public const string Invalid = "\t\r\n";
public const string LookAlike = @"O0l1I|"; public const string LookAlike = @"O0l1I|";
internal const string MenuAccels = PwCharSet.LowerCase + PwCharSet.Digits;
private const int CharTabSize = (0x10000 / 8); private const int CharTabSize = (0x10000 / 8);
private List<char> m_vChars = new List<char>(); private List<char> m_vChars = new List<char>();
private byte[] m_vTab = new byte[CharTabSize]; private byte[] m_vTab = new byte[CharTabSize];
private string m_strHighAnsi = string.Empty; private static string m_strHighAnsi = null;
private string m_strSpecial = string.Empty; public static string HighAnsiChars
{
get
{
if(m_strHighAnsi == null) { new PwCharSet(); } // Create string
Debug.Assert(m_strHighAnsi != null);
return m_strHighAnsi;
}
}
private static string m_strSpecial = null;
public static string SpecialChars
{
get
{
if(m_strSpecial == null) { new PwCharSet(); } // Create string
Debug.Assert(m_strSpecial != null);
return m_strSpecial;
}
}
/// <summary> /// <summary>
/// Create a new, empty character set collection object. /// Create a new, empty character set collection object.
/// </summary> /// </summary>
public PwCharSet() public PwCharSet()
{ {
this.Initialize(true); Initialize(true);
} }
public PwCharSet(string strCharSet) public PwCharSet(string strCharSet)
{ {
this.Initialize(true); Initialize(true);
this.Add(strCharSet); Add(strCharSet);
} }
private PwCharSet(bool bFullInitialize) private PwCharSet(bool bFullInitialize)
{ {
this.Initialize(bFullInitialize); Initialize(bFullInitialize);
} }
private void Initialize(bool bFullInitialize) private void Initialize(bool bFullInitialize)
{ {
this.Clear(); Clear();
if(bFullInitialize == false) return; if(!bFullInitialize) return;
StringBuilder sbHighAnsi = new StringBuilder(); if(m_strHighAnsi == null)
for(char ch = '~'; ch < 255; ++ch) {
sbHighAnsi.Append(ch); StringBuilder sbHighAnsi = new StringBuilder();
m_strHighAnsi = sbHighAnsi.ToString(); // [U+0080, U+009F] are C1 control characters,
// U+00A0 is non-breaking space
for(char ch = '\u00A1'; ch <= '\u00AC'; ++ch)
sbHighAnsi.Append(ch);
// U+00AD is soft hyphen (format character)
for(char ch = '\u00AE'; ch < '\u00FF'; ++ch)
sbHighAnsi.Append(ch);
sbHighAnsi.Append('\u00FF');
PwCharSet pcs = new PwCharSet(false); m_strHighAnsi = sbHighAnsi.ToString();
pcs.AddRange('!', '/'); }
pcs.AddRange(':', '@');
pcs.AddRange('[', '`'); if(m_strSpecial == null)
pcs.Remove(@"-_ "); {
pcs.Remove(PwCharSet.Brackets); PwCharSet pcs = new PwCharSet(false);
m_strSpecial = pcs.ToString(); pcs.AddRange('!', '/');
pcs.AddRange(':', '@');
pcs.AddRange('[', '`');
pcs.Add(@"|~");
pcs.Remove(@"-_ ");
pcs.Remove(PwCharSet.Brackets);
m_strSpecial = pcs.ToString();
}
} }
/// <summary> /// <summary>
@@ -118,9 +154,6 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
} }
} }
public string SpecialChars { get { return m_strSpecial; } }
public string HighAnsiChars { get { return m_strHighAnsi; } }
/// <summary> /// <summary>
/// Remove all characters from this set. /// Remove all characters from this set.
/// </summary> /// </summary>
@@ -142,7 +175,7 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
foreach(char ch in strCharacters) foreach(char ch in strCharacters)
{ {
if(this.Contains(ch) == false) return false; if(!Contains(ch)) return false;
} }
return true; return true;
@@ -156,7 +189,7 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
{ {
if(ch == char.MinValue) { Debug.Assert(false); return; } if(ch == char.MinValue) { Debug.Assert(false); return; }
if(this.Contains(ch) == false) if(!Contains(ch))
{ {
m_vChars.Add(ch); m_vChars.Add(ch);
m_vTab[ch / 8] |= (byte)(1 << (ch % 8)); m_vTab[ch / 8] |= (byte)(1 << (ch % 8));
@@ -175,20 +208,20 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
m_vChars.Capacity = m_vChars.Count + strCharSet.Length; m_vChars.Capacity = m_vChars.Count + strCharSet.Length;
foreach(char ch in strCharSet) foreach(char ch in strCharSet)
this.Add(ch); Add(ch);
} }
public void Add(string strCharSet1, string strCharSet2) public void Add(string strCharSet1, string strCharSet2)
{ {
this.Add(strCharSet1); Add(strCharSet1);
this.Add(strCharSet2); Add(strCharSet2);
} }
public void Add(string strCharSet1, string strCharSet2, string strCharSet3) public void Add(string strCharSet1, string strCharSet2, string strCharSet3)
{ {
this.Add(strCharSet1); Add(strCharSet1);
this.Add(strCharSet2); Add(strCharSet2);
this.Add(strCharSet3); Add(strCharSet3);
} }
public void AddRange(char chMin, char chMax) public void AddRange(char chMin, char chMax)
@@ -196,9 +229,9 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
m_vChars.Capacity = m_vChars.Count + (chMax - chMin) + 1; m_vChars.Capacity = m_vChars.Count + (chMax - chMin) + 1;
for(char ch = chMin; ch < chMax; ++ch) for(char ch = chMin; ch < chMax; ++ch)
this.Add(ch); Add(ch);
this.Add(chMax); Add(chMax);
} }
public bool AddCharSet(char chCharSetIdentifier) public bool AddCharSet(char chCharSetIdentifier)
@@ -207,29 +240,29 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
switch(chCharSetIdentifier) switch(chCharSetIdentifier)
{ {
case 'a': this.Add(PwCharSet.LowerCase, PwCharSet.Digits); break; case 'a': Add(PwCharSet.LowerCase, PwCharSet.Digits); break;
case 'A': this.Add(PwCharSet.LowerCase, PwCharSet.UpperCase, case 'A': Add(PwCharSet.LowerCase, PwCharSet.UpperCase,
PwCharSet.Digits); break; PwCharSet.Digits); break;
case 'U': this.Add(PwCharSet.UpperCase, PwCharSet.Digits); break; case 'U': Add(PwCharSet.UpperCase, PwCharSet.Digits); break;
case 'c': this.Add(PwCharSet.LowerConsonants); break; case 'c': Add(PwCharSet.LowerConsonants); break;
case 'C': this.Add(PwCharSet.LowerConsonants, case 'C': Add(PwCharSet.LowerConsonants,
PwCharSet.UpperConsonants); break; PwCharSet.UpperConsonants); break;
case 'z': this.Add(PwCharSet.UpperConsonants); break; case 'z': Add(PwCharSet.UpperConsonants); break;
case 'd': this.Add(PwCharSet.Digits); break; // Digit case 'd': Add(PwCharSet.Digits); break; // Digit
case 'h': this.Add(PwCharSet.LowerHex); break; case 'h': Add(PwCharSet.LowerHex); break;
case 'H': this.Add(PwCharSet.UpperHex); break; case 'H': Add(PwCharSet.UpperHex); break;
case 'l': this.Add(PwCharSet.LowerCase); break; case 'l': Add(PwCharSet.LowerCase); break;
case 'L': this.Add(PwCharSet.LowerCase, PwCharSet.UpperCase); break; case 'L': Add(PwCharSet.LowerCase, PwCharSet.UpperCase); break;
case 'u': this.Add(PwCharSet.UpperCase); break; case 'u': Add(PwCharSet.UpperCase); break;
case 'p': this.Add(PwCharSet.Punctuation); break; case 'p': Add(PwCharSet.Punctuation); break;
case 'b': this.Add(PwCharSet.Brackets); break; case 'b': Add(PwCharSet.Brackets); break;
case 's': this.Add(PwCharSet.PrintableAsciiSpecial); break; case 's': Add(PwCharSet.PrintableAsciiSpecial); break;
case 'S': this.Add(PwCharSet.UpperCase, PwCharSet.LowerCase); case 'S': Add(PwCharSet.UpperCase, PwCharSet.LowerCase);
this.Add(PwCharSet.Digits, PwCharSet.PrintableAsciiSpecial); break; Add(PwCharSet.Digits, PwCharSet.PrintableAsciiSpecial); break;
case 'v': this.Add(PwCharSet.LowerVowels); break; case 'v': Add(PwCharSet.LowerVowels); break;
case 'V': this.Add(PwCharSet.LowerVowels, PwCharSet.UpperVowels); break; case 'V': Add(PwCharSet.LowerVowels, PwCharSet.UpperVowels); break;
case 'Z': this.Add(PwCharSet.UpperVowels); break; case 'Z': Add(PwCharSet.UpperVowels); break;
case 'x': this.Add(m_strHighAnsi); break; case 'x': Add(m_strHighAnsi); break;
default: bResult = false; break; default: bResult = false; break;
} }
@@ -238,7 +271,7 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
public bool Remove(char ch) public bool Remove(char ch)
{ {
m_vTab[ch / 8] &= (byte)~(1 << (ch % 8)); m_vTab[ch / 8] &= (byte)(~(1 << (ch % 8)));
return m_vChars.Remove(ch); return m_vChars.Remove(ch);
} }
@@ -261,10 +294,10 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
Debug.Assert(strCharacters != null); Debug.Assert(strCharacters != null);
if(strCharacters == null) throw new ArgumentNullException("strCharacters"); if(strCharacters == null) throw new ArgumentNullException("strCharacters");
if(this.Contains(strCharacters) == false) if(!Contains(strCharacters))
return false; return false;
return this.Remove(strCharacters); return Remove(strCharacters);
} }
/// <summary> /// <summary>
@@ -284,16 +317,16 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.Append(this.RemoveIfAllExist(PwCharSet.UpperCase) ? 'U' : '_'); sb.Append(RemoveIfAllExist(PwCharSet.UpperCase) ? 'U' : '_');
sb.Append(this.RemoveIfAllExist(PwCharSet.LowerCase) ? 'L' : '_'); sb.Append(RemoveIfAllExist(PwCharSet.LowerCase) ? 'L' : '_');
sb.Append(this.RemoveIfAllExist(PwCharSet.Digits) ? 'D' : '_'); sb.Append(RemoveIfAllExist(PwCharSet.Digits) ? 'D' : '_');
sb.Append(this.RemoveIfAllExist(m_strSpecial) ? 'S' : '_'); sb.Append(RemoveIfAllExist(m_strSpecial) ? 'S' : '_');
sb.Append(this.RemoveIfAllExist(PwCharSet.Punctuation) ? 'P' : '_'); sb.Append(RemoveIfAllExist(PwCharSet.Punctuation) ? 'P' : '_');
sb.Append(this.RemoveIfAllExist(@"-") ? 'm' : '_'); sb.Append(RemoveIfAllExist(@"-") ? 'm' : '_');
sb.Append(this.RemoveIfAllExist(@"_") ? 'u' : '_'); sb.Append(RemoveIfAllExist(@"_") ? 'u' : '_');
sb.Append(this.RemoveIfAllExist(@" ") ? 's' : '_'); sb.Append(RemoveIfAllExist(@" ") ? 's' : '_');
sb.Append(this.RemoveIfAllExist(PwCharSet.Brackets) ? 'B' : '_'); sb.Append(RemoveIfAllExist(PwCharSet.Brackets) ? 'B' : '_');
sb.Append(this.RemoveIfAllExist(m_strHighAnsi) ? 'H' : '_'); sb.Append(RemoveIfAllExist(m_strHighAnsi) ? 'H' : '_');
return sb.ToString(); return sb.ToString();
} }
@@ -303,16 +336,16 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
if(strRanges == null) { Debug.Assert(false); return; } if(strRanges == null) { Debug.Assert(false); return; }
if(strRanges.Length < 10) { Debug.Assert(false); return; } if(strRanges.Length < 10) { Debug.Assert(false); return; }
if(strRanges[0] != '_') this.Add(PwCharSet.UpperCase); if(strRanges[0] != '_') Add(PwCharSet.UpperCase);
if(strRanges[1] != '_') this.Add(PwCharSet.LowerCase); if(strRanges[1] != '_') Add(PwCharSet.LowerCase);
if(strRanges[2] != '_') this.Add(PwCharSet.Digits); if(strRanges[2] != '_') Add(PwCharSet.Digits);
if(strRanges[3] != '_') this.Add(m_strSpecial); if(strRanges[3] != '_') Add(m_strSpecial);
if(strRanges[4] != '_') this.Add(PwCharSet.Punctuation); if(strRanges[4] != '_') Add(PwCharSet.Punctuation);
if(strRanges[5] != '_') this.Add('-'); if(strRanges[5] != '_') Add('-');
if(strRanges[6] != '_') this.Add('_'); if(strRanges[6] != '_') Add('_');
if(strRanges[7] != '_') this.Add(' '); if(strRanges[7] != '_') Add(' ');
if(strRanges[8] != '_') this.Add(PwCharSet.Brackets); if(strRanges[8] != '_') Add(PwCharSet.Brackets);
if(strRanges[9] != '_') this.Add(m_strHighAnsi); if(strRanges[9] != '_') Add(m_strHighAnsi);
} }
} }
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -18,8 +18,11 @@
*/ */
using System; using System;
using System.ComponentModel; using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization; using System.Xml.Serialization;
using System.ComponentModel;
using System.Diagnostics;
using ModernKeePassLib.Interfaces; using ModernKeePassLib.Interfaces;
using ModernKeePassLib.Security; using ModernKeePassLib.Security;
@@ -27,12 +30,12 @@ using ModernKeePassLib.Utility;
namespace ModernKeePassLib.Cryptography.PasswordGenerator namespace ModernKeePassLib.Cryptography.PasswordGenerator
{ {
/// <summary> /// <summary>
/// Type of the password generator. Different types like generators /// Type of the password generator. Different types like generators
/// based on given patterns, based on character sets, etc. are /// based on given patterns, based on character sets, etc. are
/// available. /// available.
/// </summary> /// </summary>
public enum PasswordGeneratorType public enum PasswordGeneratorType
{ {
/// <summary> /// <summary>
/// Generator based on character spaces/sets, i.e. groups /// Generator based on character spaces/sets, i.e. groups
@@ -250,14 +253,15 @@ namespace ModernKeePassLib.Cryptography.PasswordGenerator
if((ch >= 'A') && (ch <= 'Z')) pcs.Add(PwCharSet.UpperCase); if((ch >= 'A') && (ch <= 'Z')) pcs.Add(PwCharSet.UpperCase);
else if((ch >= 'a') && (ch <= 'z')) pcs.Add(PwCharSet.LowerCase); else if((ch >= 'a') && (ch <= 'z')) pcs.Add(PwCharSet.LowerCase);
else if((ch >= '0') && (ch <= '9')) pcs.Add(PwCharSet.Digits); else if((ch >= '0') && (ch <= '9')) pcs.Add(PwCharSet.Digits);
else if((@"!#$%&'*+,./:;=?@^").IndexOf(ch) >= 0) pcs.Add(pcs.SpecialChars); else if(PwCharSet.SpecialChars.IndexOf(ch) >= 0)
pcs.Add(PwCharSet.SpecialChars);
else if(ch == ' ') pcs.Add(' '); else if(ch == ' ') pcs.Add(' ');
else if(ch == '-') pcs.Add('-'); else if(ch == '-') pcs.Add('-');
else if(ch == '_') pcs.Add('_'); else if(ch == '_') pcs.Add('_');
else if(ch == '\"') pcs.Add(pcs.SpecialChars); else if(PwCharSet.Brackets.IndexOf(ch) >= 0)
else if(ch == '\\') pcs.Add(pcs.SpecialChars); pcs.Add(PwCharSet.Brackets);
else if((@"()[]{}<>").IndexOf(ch) >= 0) pcs.Add(PwCharSet.Brackets); else if(PwCharSet.HighAnsiChars.IndexOf(ch) >= 0)
else if((ch >= '~') && (ch <= 255)) pcs.Add(pcs.HighAnsiChars); pcs.Add(PwCharSet.HighAnsiChars);
else pcs.Add(ch); else pcs.Add(ch);
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -18,522 +18,117 @@
*/ */
using System; using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using ModernKeePassLib.Utility; using ModernKeePassLib.Utility;
#if !KeePassLibSD
namespace ModernKeePassLib.Cryptography namespace ModernKeePassLib.Cryptography
{ {
/// <summary> public static class PopularPasswords
/// Bloom filter-based popular password checking.
/// </summary>
public static class PopularPasswords
{ {
private const int PpcTableSize = 8192 * 8; // Bits, multiple of 64 private static Dictionary<int, Dictionary<string, bool>> m_dicts =
new Dictionary<int, Dictionary<string, bool>>();
// Bits set: 32433 of 65536 internal static int MaxLength
// Hash functions: 32 {
// Phi (bits unset ratio) estimation: 0.505455388896019 get
// Exact Phi: 0.505111694335938 {
// False positives ratio: 1.67583063859565E-10 Debug.Assert(m_dicts.Count > 0); // Should be initialized
private static readonly ulong[] PpcTable = {
0x60383D3A85560B9BUL, 0x2578CE9D37C6AEB7UL, 0xF509A5743FD03228UL, int iMaxLen = 0;
0x19B7455E8933EE56UL, 0x5EA419ADCFD9C20EUL, 0xEA618EFC0B37A162UL, foreach(int iLen in m_dicts.Keys)
0xE0FD4D1FFF1CE415UL, 0x7A649E0301BB6060UL, 0x80D9CD9F9EEB603DUL, {
0x47D6010D0D6E6CDEUL, 0x2552708C589EB554UL, 0x073F1A3DB3267502UL, if(iLen > iMaxLen) iMaxLen = iLen;
0x3313FEC2A2FEA475UL, 0x4593665C44934FEBUL, 0x410A301A23660395UL, }
0x6AD06DA533FF5659UL, 0x423DAF86F3E41F4AUL, 0x82F035A971C6FD18UL,
0xB5E9139F28C93223UL, 0x1D07C3F4160585CAUL, 0x24B01EDB6B23E2C5UL, return iMaxLen;
0xD52F25B724F936C9UL, 0x8018392517836928UL, 0x3AA4C0F8E181EDA2UL, }
0x8D93683EF7D52529UL, 0x6164BB6208114460UL, 0x737A04D8FEF3D88FUL, }
0x3400097098D5C2CBUL, 0x3C2B9ABE5C455B2EUL, 0x3A3819973AB32DA2UL,
0x38ACB428510AF40BUL, 0x83320D5114B74771UL, 0xC25BEC333B90DCD1UL, internal static bool ContainsLength(int nLength)
0x0E9F412FBA3813D1UL, 0x047E31E3098EB2B8UL, 0xBB686AC643F1741FUL, {
0x0BE22E9C0EF0E8F2UL, 0x65AA9504E5F40D31UL, 0xE018DF5D64C62AC7UL, Dictionary<string, bool> dDummy;
0x17020E9A7EFA12EDUL, 0xFC12A7C16006DE82UL, 0x8DE4747E3745346DUL, return m_dicts.TryGetValue(nLength, out dDummy);
0x31D8C051A43CECAFUL, 0xBE9AFBEF127C1B12UL, 0xAEE94B4B808BBEE2UL, }
0x3A0099CA32835B41UL, 0x59EB3173468D8C49UL, 0x6F89DB1E6DAAE9E1UL,
0x4C1ADAA837E968E4UL, 0x6E3593A56C682769UL, 0x022AD591689B5B82UL,
0x4AC33861ED978032UL, 0xF6F476E4E6A1318DUL, 0x2DA690A11AA05A23UL,
0x916FC56378C29D77UL, 0xAB3238BE22294659UL, 0x2D73A29019B28C77UL,
0xAAF26C12EC9C3C42UL, 0x058A278A24B334F9UL, 0x033BD18FB8D9BACDUL,
0x8B3833596008B07CUL, 0x280B6D093333E5E5UL, 0x2128DBE126CA3E1EUL,
0xCCF09769382472D8UL, 0x0CB6E495BD90CED6UL, 0x1303A37577C01C5AUL,
0xC8BBF4734FC34C53UL, 0x1B38B72B10F86CD5UL, 0x5098E2D6C1892E51UL,
0x2DD8065B79DB5380UL, 0x5B9A1A6D6A2292B7UL, 0xC70F751604D0497CUL,
0x911E08D7363B5213UL, 0x9F2E245273308D2EUL, 0x64D354827957F50EUL,
0x09856750F560342CUL, 0xDE091F26603F0E70UL, 0xDDE6B4E76173E3B1UL,
0xC1584AE1B26FA08EUL, 0x1EA29887837838D2UL, 0x6D7643FC67B15C54UL,
0x921E60571ED103EAUL, 0x63EB1EB33E7AFFF1UL, 0x80BA4D1F95BFD615UL,
0xEC8A1D4FC1A6B8E0UL, 0x2C46861B6DB17D1AUL, 0x01F05D06927E443BUL,
0x6172EC2EABEAD454UL, 0x21B8726C6F7C4102UL, 0x3C016CD9945C72ECUL,
0x708F77B2C0E8B665UL, 0xFC35BE2BB88974DAUL, 0x805897A33702BD61UL,
0x9A93367A6041226CUL, 0xFDAB188B6158F6BEUL, 0x5F21014A065E918CUL,
0xF4381DD77772D19CUL, 0xC664B6358AA85011UL, 0xF2639D7B3E2307E6UL,
0x3FA000D4A5A9C37AUL, 0x8F45D116ED8DC70FUL, 0x8CB8758E45C140D0UL,
0x49832B46D716236DUL, 0xCC8E4961A93065B8UL, 0x8A996533EDACEB0EUL,
0x15B35155EC56FAC1UL, 0xE7E0C6C05A9F1885UL, 0x05914F9A1D1C79F9UL,
0x730000A30B6725F0UL, 0xC95E671F8E543780UL, 0x47D68382400AF94EUL,
0x1A27F2734FE2249AUL, 0x828079C332D9C0ABUL, 0x2E9BC798EA09170EUL,
0x6B7CDAC829018C91UL, 0x7B89604901736993UL, 0xABE4EB26F47608F0UL,
0x70D5FDC88A0FF1B1UL, 0x5A1F0BAB9AB8A158UL, 0xDC89AE0A735C51A4UL,
0x36C1EA01E9C89B84UL, 0x3A9757AF204096DBUL, 0x1D56C8328540F963UL,
0x910A8694692472FAUL, 0x697192C9DF145604UL, 0xB20F7A4438712AA2UL,
0xE8C99185243F4896UL, 0xFBC8970EDBC39CA7UL, 0x33485403868C3761UL,
0xAFA97DDEDB1D6AD8UL, 0x54A1A6F24476A3BBUL, 0xFE4E078B184BDB7FUL,
0x5ED1543919754CD8UL, 0x86F8C775160FC08CUL, 0x9B4098F57019040DUL,
0x039518BBE841327BUL, 0x111D0D420A3F5F6AUL, 0x0666067346AF34ACUL,
0xD43F1D14EB239B9BUL, 0xA6BB91FEB5618F5BUL, 0xA2B5218B202409ADUL,
0xC004FA688C3AC25EUL, 0xF0E2D9EA2935E1DCUL, 0x380B31CFA2F2AF43UL,
0x50E050AE426250EAUL, 0x628ED94D1AA8F55BUL, 0xF8EB0654F0166311UL,
0x1F8858D26DDA5CC5UL, 0x931425D11CB1EFEBUL, 0xF661D461DC1A05D3UL,
0x7B75ED7EC6936DA8UL, 0x8713C59690985202UL, 0xF61D6F93F07C0E85UL,
0xFD1771F6711D6F4FUL, 0x5835A67E1B11419FUL, 0x33EF08ABD56A1050UL,
0x55B5D0043FA2C01CUL, 0x53316ED963B92D9DUL, 0x6A8C93744E521EDBUL,
0x083E948062EB9543UL, 0x1C15289B3189AFB1UL, 0xA6A0A5053AE2212DUL,
0x6573AF7F01FAFF3BUL, 0x58B6F034CFCFE843UL, 0xEB2837CA5AEA6AEDUL,
0x633E7897097AC328UL, 0x7FA91789B6CCEE82UL, 0xBEE2402F4E7D65EEUL,
0x616A103EC8FB0DBEUL, 0x65991F9FB25E13FCUL, 0x54EA8A3FADEC1F4BUL,
0x6D497C5ACDEA0E7AUL, 0x5865045E8CA18527UL, 0xA406C09215ABD61FUL,
0x68F81F5745FC9875UL, 0xE496D850CEFF3FA9UL, 0xD225C88D63212CB1UL,
0x37676390525116D2UL, 0x415614AB14188A7DUL, 0xABE58EBC1F6DDC63UL,
0xDE10312B2C25D28CUL, 0x86C86D7A0B847635UL, 0x408B511D584DC3DCUL,
0x6711FCC14B303FEDUL, 0x1284DF9CC6972023UL, 0xC3CE0B33141BFA8FUL,
0x0F3F58367D4A1819UL, 0x9313F83058FBE6D0UL, 0x6FCA5EF39B8E2F47UL,
0xA90F5C95D887756DUL, 0x96C4E2AD85D5AF6EUL, 0x0ED68A81F526F0A0UL,
0x53E4472DB4255A35UL, 0xAC581015134D58A6UL, 0x12C000D85C644FC7UL,
0x124D489B2C0FE6E4UL, 0x8FF83531C6F5D61AUL, 0x132BD6488304F73BUL,
0x110E99BC59604CB9UL, 0xC28186ACBC940C9BUL, 0x2094C07F48141230UL,
0x65FB9881A5053589UL, 0x940A3E6D72F09D69UL, 0x972A922CB14BA66EUL,
0x8D07E59C6DDD4327UL, 0xCB67F993F820157CUL, 0x65B7A54E5FB2ED6CUL,
0xC235828849576653UL, 0xA695F85479467538UL, 0x9E2BA885E63C4243UL,
0xDE64A6A5EF84C222UL, 0xC2AB9AF302080621UL, 0x88DBA09B87FA0734UL,
0xDF002765B44D02E1UL, 0xD50D8D90587CD820UL, 0x1B68B70ED179EFE1UL,
0xD6E77F8EC26AE95CUL, 0xEE57EB7C45051872UL, 0x4D2B445F36A7F9FDUL,
0x5502ABB8BB14D7F1UL, 0xAF2C0DF0406FA901UL, 0x6522833444BF4A83UL,
0xD7CB2E3FC691BE8DUL, 0x4F36F70D2E80D19AUL, 0xF6945FE911D4923BUL,
0xE3C6FE1EA47399C1UL, 0xF09EA1B2F837702CUL, 0x5122537CF97B5CB5UL,
0x0C8202B70E9BF154UL, 0x68B554AB58EB5E68UL, 0x7BF9B8052C9BEADEUL,
0x33612BFCD303810DUL, 0x03E38CF67B37DC53UL, 0x2BFDFF8691F37D5CUL,
0x4AB483D1CB1D07F6UL, 0xF071A58640639A5CUL, 0x9D6B98169B745CE1UL,
0x5F42D3E870FDCD93UL, 0x4EDF04404F258238UL, 0x2EAB6E10D65C9BB3UL,
0x5BB71411EF78DAD2UL, 0x0DE8128636A5D689UL, 0x18FDD1F484DC9365UL,
0x9896B8896941DA5BUL, 0x8BEF8E3BA4448E5FUL, 0x963A1E977CB1D2CAUL,
0x02BCF5F068D52851UL, 0x0CD783F09BFBE381UL, 0x350DA833D8C5DB47UL,
0x8D444C914D795C43UL, 0x8A00B4DFC44D9476UL, 0x4B36CBEC089E55FDUL,
0xD9D2FA1B0AC66211UL, 0x6C7FC30FA31A8B60UL, 0x9EF4504CC985AD6BUL,
0x8F2E7E5E0C00EE73UL, 0x819131CFEEBEA069UL, 0xB1E406A863E7A1B4UL,
0x501F072FF1F2AB67UL, 0xDE578BFC5ADBC264UL, 0xCDD66A09C8E13881UL,
0x4D443460CE52957FUL, 0x3B198C267976ECFAUL, 0x6B98323D8BD26522UL,
0x80161F6A489E4BF8UL, 0xE03A8AFCC7AE6872UL, 0x2484BD95A305AB27UL,
0x6ADDAA46BF25DD0EUL, 0xA429D8B00100477CUL, 0x55AEDB88A074BF2CUL,
0x63D9F9021AB8F5F3UL, 0x37858538A10C265CUL, 0xEF54C2CE9D063149UL,
0xFA5CE5AF33E2C136UL, 0xE601A559D0C391D7UL, 0x7C4ED29BBF57DC7EUL,
0x8FD0D4146DE9E900UL, 0xB58ABFA6CE6C0733UL, 0xF8D7F7743B33EAFFUL,
0x453FA782F454643CUL, 0xD01752C21AF21E66UL, 0xA50BB7913EAF05DFUL,
0x966D5B140B2F4189UL, 0x956F5638AFF3D148UL, 0x93FAA838420E8AB3UL,
0x715E26043071EABDUL, 0x01E7B458B5FD3A41UL, 0x5CFA99C4CC0492AAUL,
0x761FD391C3623044UL, 0xD39E44E9DB96B5BCUL, 0x8806C544F0534A07UL,
0x9B225CAFE97EAAC1UL, 0xEAE5E18583492767UL, 0x6B4E51E4C297F096UL,
0xFC512662EF47E41DUL, 0xB6AC60427DB46F8BUL, 0x8F137F3DB4429C9DUL,
0x04C65FBEAE9FD8D0UL, 0xEB72305958AE5022UL, 0xAA93AA14BCA2961EUL,
0x6C7547F9456CA37AUL, 0xEE6094871615BA34UL, 0x489BC8EDE0940402UL,
0x1108AEFAAD892229UL, 0x673B8B1CF6BED23EUL, 0xFDB781A75FD94DEAUL,
0x11D9E0F5D914A7BEUL, 0x02830D07F018143DUL, 0x9B3163B8188FD2BAUL,
0x32C1BEC97D06117EUL, 0x697268B761240CFFUL, 0xBD89CE3037C2E7A9UL,
0xF21C158125B19600UL, 0x632CB1931601B70AUL, 0x7BB3FB131338085CUL,
0xA9C06689B8138384UL, 0x161CCBF83EBDC2A1UL, 0x2CF83C01A80B7935UL,
0x9E51FE393B8E2FF0UL, 0xFE96E52B1606C1A7UL, 0x5E20DFB87F81ACCEUL,
0xF95DB9602CDAE467UL, 0xDEA155CD35555FEBUL, 0xF0669B810F70CDC6UL,
0xD36C2FBEB6A449ACUL, 0xCE500C6621C0A445UL, 0x41308909E366460AUL,
0xAC4D8178DA0CEC24UL, 0xC69049179ED09F7DUL, 0x36B608A0BA2FD848UL,
0xDF511894DD9568B4UL, 0xB3BFDF78EC861A6CUL, 0xCD50F39D19848153UL,
0xD2C1BC57E78A408CUL, 0x1E6613EFBB11B5EBUL, 0xF58E30D2D90F73D3UL,
0xCCB5E2F5E168D742UL, 0xEE97259469BDB672UL, 0x6784D35AF65935A8UL,
0x71032765ADED1FE8UL, 0x4BBF2FE54D9B72E3UL, 0x5A1BB7831E876A05UL,
0x12A8FC949EE91686UL, 0x8296F8FA83BD112CUL, 0xAAA7E3BFF64D34D5UL,
0x0301655E1794EE4BUL, 0x1E547C011BBF30E1UL, 0x39D74FEC536F31D6UL,
0x3C31A7478B1815BAUL, 0x525C774F82D5836EUL, 0xECF7186DC612FD8CUL,
0x96B7C4EDD1F3536FUL, 0x7E8C21F19C08541CUL, 0xEE92DB0CF91E4B09UL,
0xF666190D1591AE5DUL, 0x5E9B45102C895361UL, 0x9A95597AAE5C905DUL,
0x6E1272E5BB93F93FUL, 0x0E39E612402BFCF8UL, 0x576C9E8CA2A3B35EUL,
0x7E2E629996D0C35FUL, 0xC95DFF54E3524FCCUL, 0x260F9DEBDEB0E5CBUL,
0x577B6C6640BAF1ABUL, 0xCA76677779CA358EUL, 0x9E2714BEBCFDB144UL,
0xD660595CE30FD3EEUL, 0x72DE172D55A5706EUL, 0xB4C84D564489D420UL,
0x160AA2B9399D5A9DUL, 0x2906ECE619DAC4D2UL, 0x12CE8E8E68A4C317UL,
0x6BE2DFE89901CAA1UL, 0xEE1D68158102EB77UL, 0x64EB75E45BDA1AC5UL,
0xEFECF9F98720B55DUL, 0x41CDF813931315BFUL, 0x5F1E4F50CF98FFD4UL,
0xE69E09EED12E173BUL, 0x89A3707F0396FF65UL, 0x81E36B9DF4FFB492UL,
0x58C32E883D4DE6DDUL, 0x2D4725C2A5F0B469UL, 0x6B2B9C27CC421CACUL,
0x3C30F2AD966800C7UL, 0xFF74938BB76B8A7CUL, 0x52B5C99114FD93FAUL,
0x51647EDCA6C104DAUL, 0xEB47684CF796DF4EUL, 0x376D74A5AB14BD71UL,
0xF0871FEF8E9DAA3EUL, 0x1D65B134B2E045B6UL, 0x9DC8C0D8623BBA48UL,
0xAD6FC3C59DBDADF4UL, 0x66F6EBA55488B569UL, 0xB00D53E0E2D38F0AUL,
0x43A4212CEAD34593UL, 0x44724185FF7019FFUL, 0x50F46061432B3635UL,
0x880AA4C24E6B320BUL, 0xCAFCB3409A0DB43FUL, 0xA7F1A13DEF47514BUL,
0x3DC8A385A698220CUL, 0xFA17F82E30B85580UL, 0x430E7F0E88655F47UL,
0x45A1566013837B47UL, 0x84B2306D2292804EUL, 0xE7A3AF21D074E419UL,
0x09D08E2C5E569D4DUL, 0x84228F8908383FA2UL, 0xC34079610C8D3E82UL,
0x66C96426C54A5453UL, 0xD41F164117D32C93UL, 0x7829A66BF1FEC186UL,
0x4BB6846694BDFC18UL, 0x857D1C1C01352C01UL, 0xAB8E68BA85402A45UL,
0x74B3C4F101FE76C8UL, 0x6CF482CFAFB29FFEUL, 0x28B174A18F4DC3D1UL,
0x833C3425B2AA3755UL, 0x8AA58A32747F4432UL, 0xFE7B9FB4BCE3CD58UL,
0xB0836B2C16FA5553UL, 0x1D08EE6861BF3F23UL, 0x0FAE41E914562DF3UL,
0xB10A2E041937FC57UL, 0xDA60BB363415BF4CUL, 0xEEC67DBAB4CF4F0AUL,
0x9A6ED59FCC923B5CUL, 0x9A913C01A8EC7A83UL, 0xAD4779F2F9C7721FUL,
0x2BF0B7D105BE7459UL, 0x189EFA9AD5195EC6UL, 0xB5C9A2DD64B2A903UL,
0x5BCD642B2C2FD32CUL, 0xFED3FBF78CB0891FUL, 0x1ED958EE3C36DD3FUL,
0x030F5DE9CA65E97CUL, 0xBB5BCF8C931B85FEUL, 0xFD128759EA1D8061UL,
0x2C0238AC416BE6BCUL, 0xBB018584EEACFA27UL, 0xCEA7288C1964DE15UL,
0x7EA5C3840F29AA4DUL, 0x5DA841BA609E4A50UL, 0xE53AF84845985EB1UL,
0x93264DA9487183E4UL, 0xC3A4E367AF6D8D15UL, 0xDD4EB6450577BAF8UL,
0x2AA3093EE2C658ACUL, 0x3D036EC45055C580UL, 0xDDEDB34341C5B7DFUL,
0x524FFBDC4A1FAC90UL, 0x1B9D63DE13D82907UL, 0x69F9BAF0E868B640UL,
0xFC1A453A9253013CUL, 0x08B900DECAA77377UL, 0xFF24C72324153C59UL,
0x6182C1285C507A9BUL, 0x4E6680A54A03CCC8UL, 0x7165680200B67F1FUL,
0xC3290B26A07DCE5BUL, 0x2AD16584AA5BECE9UL, 0x5F10DF677C91B05EUL,
0x4BE1B0E2334B198AUL, 0xEA2466E4F4E4406DUL, 0x6ECAA92FF91E6F1DUL,
0x0267738EFA75CADDUL, 0x4282ED10A0EBFCF2UL, 0xD3F84CE8E1685271UL,
0xB667ED35716CA215UL, 0x97B4623D70DB7FA8UL, 0xB7BA3AA5E6C2E7CBUL,
0x8942B2F97118255BUL, 0x009050F842FB52ADUL, 0x114F5511999F5BD5UL,
0x70C1CAAF1E83F00AUL, 0xAC8EE25D462BB1AAUL, 0x63EEF42AD4E1BED9UL,
0x58DFBB3D22D3D1A5UL, 0x82B0027C0C63D816UL, 0x48D038F08F3D848BUL,
0xCE262D5F9A12610EUL, 0xA54BF51C21BD0167UL, 0xF3645F6FB948397DUL,
0x9188AE58532DA501UL, 0xEC90B0E1479DB767UL, 0x37F4886B83724F80UL,
0x232B8FF20ACD95AFUL, 0x88A228285D6BCDF0UL, 0x321FB91600259AEEUL,
0xA1F875F161D18E5EUL, 0x5B6087CDA21AEA0CUL, 0x0156923ED1A3D5F1UL,
0xC2892C8A6133B5D3UL, 0x015CA4DF0EA6354DUL, 0x5E25EB261B69A7D4UL,
0xAAA8CF0C012EFBA7UL, 0xCF3466248C37868BUL, 0x0D744514BD1D82C0UL,
0xB00FF1431EDDF490UL, 0xC79B86A0E3A8AB08UL, 0xFC361529BC9F1252UL,
0x869285653FB82865UL, 0x9F1C7A17546339ABUL, 0xE31AA66DBD5C4760UL,
0x51B9D2A765E0FC31UL, 0x31F39528C4CD13D8UL, 0x16C6C35B0D3A341DUL,
0x90296B1B0F28E2CDUL, 0x36338472A8DB5830UL, 0xA648E6D44DF14F87UL,
0x93E231E65EB1823FUL, 0x95AA7B9D08E2B627UL, 0x7932D149374700C7UL,
0x09EFE0A8BF245193UL, 0x742AA63BCEAFD6D8UL, 0x82D4BC5FEDF158B7UL,
0x02CDEA673CFF150DUL, 0xD8D7B5813B602D15UL, 0xA5A7B670EF15A5EDUL,
0x4C08E580A1D46AF2UL, 0xC3CA9B905D035647UL, 0x6A39ABB02F6F1B83UL,
0xD2EC2169F4D02436UL, 0x8E6AEA4DF8515AF2UL, 0x7B3DD4A8693CA2DAUL,
0xC2ABF17A50AEC383UL, 0xD4FB84F8B6D4F709UL, 0x2839A3EAA2E4C8A7UL,
0x5D5FD278FE10E1E9UL, 0x5610DDF74125D5A7UL, 0xA484B0B83461DCEAUL,
0xA511920C0A502369UL, 0xC53F30C6A5394CA4UL, 0x528799285D304DD4UL,
0xF6D7914CB252BB48UL, 0x892129CB52E65D15UL, 0x15A81B70519ACE6FUL,
0x5CFBFFD7A2A1C630UL, 0x3B900509C82DF46DUL, 0x19C3CE05D66D5FFCUL,
0x937D521A4A4799A0UL, 0xD0AE34A6EAD7207DUL, 0x3258A69F1D1A1B38UL,
0xB173E3255723CC02UL, 0xD7E48FEF7F414F1BUL, 0xDCEBA75F5C761ABEUL,
0x6DA10C618DEA0D17UL, 0x423FA8B05954FBD1UL, 0x7E73C2E7D923F3C9UL,
0xC22E21C927C684D1UL, 0x756BAA758764685FUL, 0x8C90B4C4E741D880UL,
0x1B658C9F4B41D846UL, 0x5D80C14094366707UL, 0xB55FED3E03C00F2DUL,
0x9B69EB7964C69C83UL, 0x356ED81C9494DADDUL, 0x7599AFF0B2A339D6UL,
0xA5EBFD25C9B5816BUL, 0xA481DC1C8995E1EFUL, 0xE42C63DF0D402397UL,
0x3B497B4C30873BAAUL, 0xA950B78BA8772C96UL, 0xD46308D4C76F115DUL,
0x73714A4ACA76A857UL, 0x0DA86B958FF8CB7DUL, 0xEB61F617B90E0A75UL,
0xD6106C9B39F51F55UL, 0xB179F73A6BD23B59UL, 0xE7F056E50104A460UL,
0xBC5B5387634A8642UL, 0xE1678D8752996AF4UL, 0xB508F3D394664A4BUL,
0xC88536DC4A219B0FUL, 0x39964CBB8CE367B1UL, 0xD51E211D5E9E1417UL,
0x6821B97B496870F2UL, 0xA596257350CA0A99UL, 0x6D051EE2C49D4D1DUL,
0xCB426AD61AA8D9B5UL, 0x5FFD3A4062B06D22UL, 0xDAD37BF2A4C594EBUL,
0x6B9CC848E2B0C686UL, 0x19B4232F3BC622AEUL, 0x70C13C7E5950B702UL,
0x383318CA622101ACUL, 0xD9647C028CD1C4DFUL, 0x006D123BC553B93CUL,
0x2CA9D7D896EAE722UL, 0xF19872AC8A0BD5A8UL, 0x59838578EB9E8E5CUL,
0xB948621EE99B27D4UL, 0x2B470E6036E0E387UL, 0xD0A7E8F0C8A32A84UL,
0xCBF869271A8E0914UL, 0x705F76A5EA4437CFUL, 0xBAD2BF4933215152UL,
0xE52EDE847038EA23UL, 0xB8A3EFD3D58D7607UL, 0x748472F5AD330239UL,
0xCC079CFD428690F6UL, 0x3687450CB7534DACUL, 0x0FEF82D5CC8ACE2AUL,
0x214653D5C552CA9AUL, 0x9FCA4E87BF6A04FDUL, 0x78D4B114D234A0D7UL,
0x22840422BD6A5BB5UL, 0x5B9ABE0DE1B4410FUL, 0xB3B50007963FDD6BUL,
0x53A8A46793B68E35UL, 0x8CDD8E8D188B6033UL, 0x5DD22B6E3ED49572UL,
0xE561F5D27F5302D6UL, 0xDF89CEC3322E56CDUL, 0x87167F503D600F90UL,
0x1698BB71C8201862UL, 0xF7BF5DFDB023108EUL, 0xA17FB15B66ACFB5FUL,
0x2DD771987768073BUL, 0x19299D2D86E0EB29UL, 0x8B537B7F206EED29UL,
0xE536DA153325ABFCUL, 0x30A69976796DB3B9UL, 0x8E65A2C94E2D4981UL,
0xC301D53553BD6514UL, 0x46DF3639B9E43790UL, 0x3004CD0E5AFD0463UL,
0x46E460B0F6ACA1A0UL, 0xCBA210E7372D9BD5UL, 0x45064274A74CA582UL,
0xFDD57EA43CE631AEUL, 0xF2BA08FFA4A683D0UL, 0x8DA658C4DAD42999UL,
0x7418042943E88040UL, 0x96000F72E9371FEFUL, 0xE9F1212DC8F47302UL,
0x2AFB565ECC3553EDUL, 0xCD3D55137EFF7FD6UL, 0xD36F11059388E442UL,
0xC4B47515DB5709DDUL, 0x5C363EFBF0BAAB67UL, 0x28C63B5A31650BBBUL,
0x6AE54E5068061C81UL, 0xDEE62000F4E0AA21UL, 0xE8238672FE088A8BUL,
0x9869CB6370F075B9UL, 0xBA376E2FC7DB330FUL, 0xB0F73E208487CDEEUL,
0x359D5017BE37FE97UL, 0x684D828C7F95E2DCUL, 0x9985ECA20E46AE1FUL,
0x8030A5137D1A21C4UL, 0xF78CDC00FC37AC39UL, 0x41CDDC8E61D9C644UL,
0xB6F3CD1D833BAD1DUL, 0x301D0D858A23DE22UL, 0xA51FCA12AD849BC8UL,
0x9F55E615986AB10EUL, 0x904AAA59854F2215UL, 0x12ECEA4AB40F51A7UL,
0xB4EDF5807735E23BUL, 0x6190200F1C589478UL, 0xA3CA57F321909A5AUL,
0x0BFAEE04B7325B63UL, 0x10C393E7FBCF826DUL, 0x4050A2CA53FDA708UL,
0xF31114A9B462B680UL, 0x6FB9A6F121BA2006UL, 0x04550CF09389D602UL,
0xB8C7D6D8CA8942F7UL, 0x71BB430C6436E9D1UL, 0xD9070DD5FAA0A10AUL,
0x8FD6827757D07E5BUL, 0xD04E6C313F8FD974UL, 0x2CFDEA1187909B9AUL,
0xC7A8E758C115F593UL, 0xA79A17663009ACC2UL, 0x8091A6B5372B141DUL,
0xEB33B08767F5BA73UL, 0xDAC1F6823B6111C7UL, 0x697DF90C3515611BUL,
0xCC1005F198761F48UL, 0x5067E4F5303B45A1UL, 0x04816D292A2D9AC2UL,
0x2949C7A0874DD5E9UL, 0x25DB2547804CEE5EUL, 0x7EDC3A8946D6F229UL,
0x00B586F67FD0C622UL, 0x3CAE5798E40324E0UL, 0x0A4F1437DE637164UL,
0x5F59B2B715871981UL, 0x5D68FF31051E48FBUL, 0x0F2C369D73A2AA46UL,
0xB009C6B53DD23399UL, 0xC366A81277084988UL, 0x5AF0E0CA0711E730UL,
0x7AD831A9E9E854BAUL, 0x1DD5EDB0CA4E85AEUL, 0x54651209D259E9DDUL,
0x3EBB1D9DAB237EADUL, 0xDA96989317AC464CUL, 0xBFCB0F8FBC52C74EUL,
0x9597ACB9E27B692EUL, 0x6F436B1643C95B23UL, 0xB81A1253E1C3CD9DUL,
0x7B35F37E905EC67EUL, 0x29CE62666EDA76DDUL, 0xFF2490DC1EC4014DUL,
0x2D4FF9124DD6B5C4UL, 0xB9510FEC23E0E9D1UL, 0x8BCDBC56541ED071UL,
0x5414E097C1B0CCB2UL, 0x82BEF8213076F5C7UL, 0xE9FC9A71BD512615UL,
0xCF15ECC39490DF5AUL, 0x49FA9328D8EE97DBUL, 0x5F80FF0153BC2145UL,
0xF63BA156B55BCB02UL, 0x0E3B9113109FDF36UL, 0x8FCD6528F54EDE69UL,
0x5D6AE9C000054763UL, 0x326D873633431FBBUL, 0x380E07FFCEF7A978UL,
0xDCAA09874A1DF230UL, 0x601494F49F6D261EUL, 0x856159486C9B60E3UL,
0x85C7F822D07089A5UL, 0xAFFB99CF5AB836C2UL, 0x241AD414FBBB956BUL,
0x0CFC042822831692UL, 0x382B16D049727FF2UL, 0x784F9997633C819AUL,
0x5C40ED725F6C390AUL, 0x2CE78B7A3331BA9CUL, 0x9C80636639963B41UL,
0x1B2D41C968355018UL, 0xD189B57691FB60E4UL, 0x3BD599A9DD85CE31UL,
0x46FC8E2EF0B9A77CUL, 0x1A389E07D0075EA4UL, 0x1622CA52401DF2ACUL,
0x528F3FF9B7993BFAUL, 0xF16C176CCA292DDBUL, 0x6C154010961EF542UL,
0x04B78E92BF6C82DFUL, 0x7D9AFEA6ABB46072UL, 0x3BC573291CBFFC2EUL,
0x277FFF096D567AF3UL, 0x1CBEB86841A6F757UL, 0xD0BCD49E76CA20A7UL,
0x25B6024756B1FE90UL, 0xE685C04EF84881FBUL, 0xDCAB14B352FC442EUL,
0x4FF80A521719953DUL, 0xD10425E411DBE94BUL, 0x60998D0507D6E38DUL,
0x146AA432C981BD5EUL, 0x1729A596282AAA41UL, 0x152BE1A263BAF963UL,
0x15278DF497D254CAUL, 0xE4B5E9891E88A5DAUL, 0x087FA3472067D0ACUL,
0xD99C2899A0AD9158UL, 0x5040F234DC531236UL, 0x9D7E1531259EEE90UL,
0x29AFB8B49391036EUL, 0x84B619599642D68EUL, 0xE838AAE0F249545CUL,
0x42D524BA8BB96959UL, 0x9A5B3E817A20EE59UL, 0x584F0530EC4C566BUL,
0xD6544FD14B47F945UL, 0x3613FB3B553A7CDEUL, 0x284E92B56831AA56UL,
0xCEE89BA10E951A22UL, 0x476806FA1A8A44E0UL, 0xC84CEF151885C1DFUL,
0x3DB1D5C1B0B73936UL, 0x45D2D90FDF452388UL, 0x038A7DD71BC5DD21UL,
0x2AC90C7422C56819UL, 0x4742046638ECE0FBUL, 0x553B44360FC8495DUL,
0xC8DBA1CF3F9A6E97UL, 0xF85919F494CAB021UL, 0x1479455C2FF236AFUL,
0x29BCAD159F7D018DUL, 0x016DFF51CBA3BCC5UL, 0x234BF8A77F6B1CF5UL,
0x20564C6F44F9E641UL, 0x063A550C5AA50FA8UL, 0xB063D0AAAA96DFECUL,
0x3EC659DF42C092F8UL, 0x29D4A76A5A5F7E09UL, 0x65EFF3EE6E691D1EUL,
0xBD1634F5721CF799UL, 0xE85BD016723B43FFUL, 0x5233E9E7AEA11022UL,
0x8C68852EA9039B4CUL, 0x2C978ADBE885BC15UL, 0x726615ED9D497550UL,
0x7C1E145EB8D2BD96UL, 0xC2FEFB25935A5D71UL, 0x9EE9C3E1C3DE416FUL,
0xFFD568A03E20E0B3UL, 0xF53649AD90156F2AUL, 0x0331B91DCE54E7EDUL,
0x67CED5A86E99392FUL, 0x16FC0A5815500B05UL, 0x030392E8D24A7C00UL,
0x232E5E31DF32A7B5UL, 0xCC8BF22B1947DF21UL, 0x4EC2C72D9C1EEABDUL,
0x0B1B79F45220E668UL, 0xCC3CF0EE9C4A899BUL, 0xFC260A60592EBC80UL,
0xC1989A0382CB03EDUL, 0x35FE679A6CD800B2UL, 0x8A6B1ADE4FBB162FUL,
0xB0FD284563625295UL, 0xCDCC1C7B2181D024UL, 0x5B8BA0C895C0BB23UL,
0xA681FEA9ADCD43DBUL, 0x0FE30FB6876DE718UL, 0x6DDD1E27B769C494UL,
0x83A1E58460FFE8BBUL, 0x8FAD6FD2DC90FF65UL, 0x41BB28B81201CB24UL,
0xA148CE79B2597204UL, 0x7CB87DF97BB477A6UL, 0x9F79E6DED87DC688UL,
0xE044D84A6C758171UL, 0x1A29E750D9EC4097UL, 0x8445FC2B80C4A0F5UL,
0x5EFD9784AFED4ED2UL, 0x344C252BD90EB0E4UL, 0xEAD18D2E4418E5B5UL,
0x207EF4FFC260BD24UL, 0xD2E5C3AE534EC538UL, 0x2F5A59BF3D10E7E1UL,
0x9528E29266C2924CUL, 0x0121B6BDAB45D138UL, 0xADD0256ACBC771DDUL,
0x7301769600C6C50DUL, 0x3E7404EA8231D497UL, 0xB39B3840B8D03117UL,
0x56EFCEDDEF5B6634UL, 0xE6BE2C0D73B72098UL, 0x5A2841A21A5E4959UL,
0xCFEB3586156DF6E0UL, 0xD84F58901E2D65B8UL, 0x79796786CCC59703UL,
0x13BFA9A94DD07696UL, 0x7B63116A6B5458B6UL, 0x1406628176C932E0UL,
0xDD7ACC4E97F91B1AUL, 0xC82B8F84A56BDBE8UL, 0x325D87D08ED8B0B0UL,
0x3F7847B1E82002DDUL, 0x4662900D2ADAF6BFUL, 0x12AE9F58561DB1D7UL,
0xA896E956A95CC074UL, 0xAA4FA3A2F8BA4084UL, 0x1D577E35F5DCA67FUL,
0x796FF2D75469DEC2UL, 0xBD3F3F87E4DE894EUL, 0x3666B2262DEBFB6BUL,
0x1E26D7AEEF976C2EUL, 0x6BC3854F867AC4A0UL, 0x743DBF8C2E95A821UL,
0xA62A76B9AE2E645AUL, 0xB4D76561F40187C1UL, 0xD3E5F23F9FA5DB25UL,
0x34B1F6B39E6A87E2UL, 0x7DA5C3DFF7BE72CFUL, 0xFDF46B1BE80AD4F9UL,
0x0B21121CA9653B8AUL, 0x1199CA9D0A90F21AUL, 0x6021EA302D01E0BAUL,
0x8101D063C05CF5D4UL, 0xE2652410DFE78F23UL, 0x84095ACF47C21A25UL,
0xD7E29A4DB2FD3A99UL, 0x7793C0CB57959F93UL, 0x94C605308B9E5AA7UL,
0x943DB1AC54165B8FUL, 0xC1391A544C07447CUL, 0x3FEF1A61F785D97BUL,
0x6DFCC3152478BDE4UL, 0x312AFB0E1982933AUL, 0xB8069C2605631ED3UL,
0x5A6076423430BED2UL, 0x34E379F09E2D4F42UL, 0x9167F5E4019573E3UL,
0x18F81157828D2A49UL, 0xF4A8723B4955EAB8UL, 0x0BE6C0ABFEA9E8A6UL,
0xC63ADCF2CEF25556UL, 0xC5EBD3BEAE9F364FUL, 0xA301D60CF5B6F2FCUL,
0x8C606CA881D27A00UL, 0x826FEE13B554C18AUL, 0x8DF251716F10B776UL,
0xB2573A33AC7D94FFUL, 0xC0E771248CB7ABB9UL, 0x753DD605DB38F4EAUL,
0x21901664C3D92114UL, 0xA408FCB7A1892612UL, 0x3084FC64A03D6722UL,
0xC8C9D9569AD42A34UL, 0x1FBFBAFC1694B383UL, 0x1894280CC3F94ABEUL,
0xE14C38A7BBB54651UL, 0x23A48CC84A6EB704UL, 0xD034ADC45AABEDBDUL,
0xC93F2C21C973C766UL, 0x66A8AEC11D743CC6UL, 0xB4F72AA52E37C145UL,
0xB02834DF0D9266B4UL, 0xDB8E724EA1FF402FUL, 0x531E9C058112E352UL,
0xC2F692531DB317D2UL, 0xEFC9586498D263A7UL, 0x84F2C524D2F3ADB9UL,
0xAFAF02C27CF25D08UL, 0x385873595F9CFC09UL, 0x36DDA10D1A152B7AUL,
0x9F9B997A0DACFB55UL, 0x10AB5EB5C4714882UL, 0x7BA4E8703E22B7EEUL,
0x0A2BFD558607BCC8UL, 0x201D3706F74F8BA1UL, 0x3DBD573B1358F02EUL,
0x5B37645FA93BCEBCUL, 0xC0166864BC1A7544UL, 0x45C7AA5559FC65D7UL,
0xEFEA04AA83349B78UL, 0x607859194F9E9FD8UL, 0xA6B9AE5B53CF7710UL,
0x73B9142ACBC50821UL, 0x8B7D67495887E65CUL, 0x39B6C4FB2B232E56UL,
0xD212DB10E31D2A68UL, 0x629AC0A3D263DC6EUL, 0x6BC2E7FF912050BAUL,
0xE0AD5A8FDB183F62UL, 0xF05648134F0C6F0FUL, 0x31E146F4AF980FDAUL,
0x7FAF0078D84D62CCUL, 0xE13F044C2830D21EUL, 0x49A047AD204B4C4BUL,
0xF3AFBE2237351A74UL, 0x32826C9217BB07EDUL, 0xD4C3AEB099319B5CUL,
0x49CE5BD05B2B0F61UL, 0x75DD36984DCBD0A2UL, 0x84EC5D7C2F0AAC6CUL,
0x8E59CC9B9942EDDFUL, 0x89FF85DCDF9AE895UL, 0x6F9EE0D8D9E8D414UL,
0x10E01A59058D3904UL, 0x1DFAF567BFF55D2EUL, 0x8DD6A18C03382CD4UL,
0xE12FD89A0CF58553UL, 0xE245DA902C0C4F5CUL, 0x8BE7566B9987520DUL,
0x4CA1C0A4B38A3098UL, 0x81E45015BE618A72UL, 0xA80E0344FF27EFDFUL,
0xC98DAEC6DC5005BAUL, 0xF56873F3A958AE5EUL, 0xDB88604670C794ACUL,
0x4F68E448DDF6535FUL, 0x3443DBF1CA6031A8UL, 0x73DFA5DEEF409A41UL,
0xA7C556941F6643B2UL, 0x424BC40D8C83D962UL, 0x6F292A325B99B726UL,
0x6EECB1009717D65EUL, 0x899BE4CE7BB2D8EEUL, 0x25285FED3E59781DUL,
0x14C5AEDD76E092D3UL, 0x9BB5EE10567640AEUL, 0xCD62A1D43558FD06UL,
0x70A7B09FC5F39447UL, 0xF10064AE92EFFB99UL, 0xD55FA1A918A23082UL,
0xD03F28AD25C73A78UL, 0x76CFFFEE094D8B0EUL, 0x4FD5A46AD5A4B4CFUL,
0x8F3A36F9D7BF87E3UL, 0x64224315210625BEUL, 0x749A131B71B64350UL,
0x9034FF9DAC089F48UL, 0xB58D3017E7321217UL, 0x549D818937D5CE90UL,
0x903CE1452419E99CUL, 0xFD052F0388DB2E76UL, 0x7390051E3972480EUL,
0x5E5F6EC3F27B3679UL, 0x3E3637D4D4EE917DUL, 0x4FE04068CA2A4309UL,
0x98C9C17454AAE42DUL, 0x659AE0BDB113BC21UL, 0x4C0BDECB1511AF4CUL,
0x17048BFAEAC0006DUL, 0x68F106AADAA64912UL, 0x2286234ECEB7EAF0UL,
0x350CD42CAF697E51UL, 0x8DCDE6D1FAC19A9FUL, 0xF97E55A245A8A8A2UL,
0xAAE86B2092DA90A3UL, 0x5123E878AA8AEF76UL, 0x022B88B9694A55F6UL,
0xC4C1A9B1C0221985UL, 0x20056D91DD5E0FFEUL, 0xF5BF61EC225C9843UL,
0x1A315A05BDCF4A31UL, 0x5710A21A8DF4F15FUL, 0x99BD1A0AF97AD027UL,
0x7602C5997AD4E12CUL
};
public static bool IsPopularPassword(char[] vPassword) public static bool IsPopularPassword(char[] vPassword)
{ {
Debug.Assert(PpcTable.Length == (PpcTableSize / 64)); ulong uDummy;
return IsPopularPassword(vPassword, out uDummy);
}
public static bool IsPopularPassword(char[] vPassword, out ulong uDictSize)
{
if(vPassword == null) throw new ArgumentNullException("vPassword"); if(vPassword == null) throw new ArgumentNullException("vPassword");
if(vPassword.Length == 0) return false; if(vPassword.Length == 0) { uDictSize = 0; return false; }
foreach(char ch in vPassword) string str = new string(vPassword);
try { return IsPopularPasswordPriv(str, out uDictSize); }
catch(Exception) { Debug.Assert(false); }
uDictSize = 0;
return false;
}
private static bool IsPopularPasswordPriv(string str, out ulong uDictSize)
{
Debug.Assert(m_dicts.Count > 0); // Should be initialized with data
Dictionary<string, bool> d;
if(!m_dicts.TryGetValue(str.Length, out d))
{ {
if(!IsPopularChar(ch)) return false; uDictSize = 0;
return false;
} }
byte[] pbUtf8 = StrUtil.Utf8.GetBytes(vPassword); uDictSize = (ulong)d.Count;
return d.ContainsKey(str);
}
int[] vIndices = GetTableIndices(pbUtf8, PpcTableSize); public static void Add(byte[] pbData, bool bGZipped)
Array.Clear(pbUtf8, 0, pbUtf8.Length); {
try
foreach(int iIndex in vIndices)
{ {
if(!GetTableBit(PpcTable, iIndex)) return false; if(bGZipped)
} pbData = MemUtil.Decompress(pbData);
return true; string strData = StrUtil.Utf8.GetString(pbData, 0, pbData.Length);
} if(string.IsNullOrEmpty(strData)) { Debug.Assert(false); return; }
private static bool IsPopularChar(char ch) if(!char.IsWhiteSpace(strData[strData.Length - 1]))
{ strData += "\n";
return (((ch >= 'A') && (ch <= 'Z')) || ((ch >= 'a') && (ch <= 'z')) ||
((ch >= '0') && (ch <= '9')) || (ch == '_') || (ch == '!'));
}
private static int[] GetTableIndices(byte[] pbPasswordUtf8, int nTableSize) StringBuilder sb = new StringBuilder();
{ for(int i = 0; i < strData.Length; ++i)
Debug.Assert(false, "not yet implemented");
return null;
#if TODO
Debug.Assert((nTableSize >= 2) && (nTableSize <= 0x10000));
Debug.Assert((nTableSize % 64) == 0);
SHA512Managed sha = new SHA512Managed();
byte[] pbHash = sha.ComputeHash(pbPasswordUtf8);
int[] vIndices = new int[pbHash.Length / 2];
for(int i = 0; i < vIndices.Length; ++i)
vIndices[i] = ((((int)pbHash[i * 2] << 8) |
(int)pbHash[i * 2 + 1]) % nTableSize);
return vIndices;
#endif
}
private static bool GetTableBit(ulong[] vTable, int iBit)
{
return ((vTable[iBit >> 6] & (1UL << (iBit & 0x3F))) != 0UL);
}
#if (DEBUG && !KeePassLibSD && TODO)
private static bool SetTableBit(ulong[] vTable, int iBit)
{
if(GetTableBit(vTable, iBit)) return false;
vTable[iBit >> 6] = (vTable[iBit >> 6] | (1UL << (iBit & 0x3F)));
return true;
}
public static void MakeList()
{
string strData = File.ReadAllText("MostPopularPasswords.txt", StrUtil.Utf8);
strData += " ";
CharStream cs = new CharStream(strData);
List<string> vPasswords = new List<string>();
StringBuilder sbPassword = new StringBuilder();
while(true)
{
char ch = cs.ReadChar();
if(ch == char.MinValue) break;
if(char.IsWhiteSpace(ch))
{ {
string strPassword = sbPassword.ToString(); char ch = strData[i];
strPassword = strPassword.ToLower();
if(strPassword.Length > 3) if(char.IsWhiteSpace(ch))
{ {
if(vPasswords.IndexOf(strPassword) < 0) int cc = sb.Length;
vPasswords.Add(strPassword); if(cc > 0)
{
string strWord = sb.ToString();
Debug.Assert(strWord.Length == cc);
Dictionary<string, bool> d;
if(!m_dicts.TryGetValue(cc, out d))
{
d = new Dictionary<string, bool>();
m_dicts[cc] = d;
}
d[strWord] = true;
sb.Remove(0, cc);
}
} }
else sb.Append(char.ToLower(ch));
sbPassword = new StringBuilder();
}
else
{
Debug.Assert(!char.IsControl(ch) && !char.IsHighSurrogate(ch) &&
!char.IsLowSurrogate(ch) && !char.IsSurrogate(ch));
Debug.Assert(IsPopularChar(ch));
sbPassword.Append(ch);
} }
} }
catch(Exception) { Debug.Assert(false); }
ulong[] vTable = new ulong[PpcTableSize / 64];
Array.Clear(vTable, 0, vTable.Length);
long lBitsInTable = 0;
foreach(string strPassword in vPasswords)
{
byte[] pbUtf8 = StrUtil.Utf8.GetBytes(strPassword);
int[] vIndices = GetTableIndices(pbUtf8, PpcTableSize);
foreach(int i in vIndices)
{
if(SetTableBit(vTable, i)) ++lBitsInTable;
}
}
StringBuilder sb = new StringBuilder();
sb.Append("\t\t\t");
for(int i = 0; i < vTable.Length; ++i)
{
if(i > 0)
{
if((i % 3) == 0)
{
sb.AppendLine(",");
sb.Append("\t\t\t");
}
else sb.Append(", ");
}
sb.Append("0x");
sb.Append(vTable[i].ToString("X16"));
sb.Append("UL");
}
sb.AppendLine();
sb.AppendLine();
sb.AppendLine("Bits set: " + lBitsInTable.ToString() + " of " +
PpcTableSize.ToString());
int cHashFn = GetTableIndices(StrUtil.Utf8.GetBytes("Dummy"), PpcTableSize).Length;
sb.AppendLine("Hash functions: " + cHashFn.ToString());
double dblPhi = Math.Pow(1.0 - ((double)cHashFn / PpcTableSize),
(double)vPasswords.Count);
sb.AppendLine("Phi (bits unset ratio) estimation: " +
dblPhi.ToString(CultureInfo.InvariantCulture));
dblPhi = ((double)(PpcTableSize - lBitsInTable) / (double)PpcTableSize);
sb.AppendLine("Exact Phi: " + dblPhi.ToString(CultureInfo.InvariantCulture));
sb.AppendLine("False positives ratio: " + Math.Pow(1.0 - dblPhi,
(double)cHashFn).ToString(CultureInfo.InvariantCulture));
File.WriteAllText("Table.txt", sb.ToString());
} }
#endif
} }
} }
#endif

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -19,9 +19,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Text; using System.Text;
using System.Diagnostics;
using ModernKeePassLib.Cryptography.PasswordGenerator;
using ModernKeePassLib.Utility; using ModernKeePassLib.Utility;
namespace ModernKeePassLib.Cryptography namespace ModernKeePassLib.Cryptography
@@ -32,13 +33,286 @@ namespace ModernKeePassLib.Cryptography
/// </summary> /// </summary>
public static class QualityEstimation public static class QualityEstimation
{ {
private enum CharSpaceBits : uint private static class PatternID
{ {
Control = 32, public const char LowerAlpha = 'L';
Alpha = 26, public const char UpperAlpha = 'U';
Number = 10, public const char Digit = 'D';
Special = 33, public const char Special = 'S';
High = 112 public const char High = 'H';
public const char Other = 'X';
public const char Dictionary = 'W';
public const char Repetition = 'R';
public const char Number = 'N';
public const char DiffSeq = 'C';
public const string All = "LUDSHXWRNC";
}
// private static class CharDistrib
// {
// public static readonly ulong[] LowerAlpha = new ulong[26] {
// 884, 211, 262, 249, 722, 98, 172, 234, 556, 124, 201, 447, 321,
// 483, 518, 167, 18, 458, 416, 344, 231, 105, 80, 48, 238, 76
// };
// public static readonly ulong[] UpperAlpha = new ulong[26] {
// 605, 188, 209, 200, 460, 81, 130, 163, 357, 122, 144, 332, 260,
// 317, 330, 132, 18, 320, 315, 250, 137, 76, 60, 36, 161, 54
// };
// public static readonly ulong[] Digit = new ulong[10] {
// 574, 673, 524, 377, 339, 336, 312, 310, 357, 386
// };
// }
private sealed class QeCharType
{
private readonly char m_chTypeID;
public char TypeID { get { return m_chTypeID; } }
private readonly string m_strAlph;
public string Alphabet { get { return m_strAlph; } }
private readonly int m_nChars;
public int CharCount { get { return m_nChars; } }
private readonly char m_chFirst;
private readonly char m_chLast;
private readonly double m_dblCharSize;
public double CharSize { get { return m_dblCharSize; } }
public QeCharType(char chTypeID, string strAlphabet, bool bIsConsecutive)
{
if(strAlphabet == null) throw new ArgumentNullException();
if(strAlphabet.Length == 0) throw new ArgumentException();
m_chTypeID = chTypeID;
m_strAlph = strAlphabet;
m_nChars = m_strAlph.Length;
m_chFirst = (bIsConsecutive ? m_strAlph[0] : char.MinValue);
m_chLast = (bIsConsecutive ? m_strAlph[m_nChars - 1] : char.MinValue);
m_dblCharSize = Log2(m_nChars);
Debug.Assert(((int)(m_chLast - m_chFirst) == (m_nChars - 1)) ||
!bIsConsecutive);
}
public QeCharType(char chTypeID, int nChars) // Catch-none set
{
if(nChars <= 0) throw new ArgumentOutOfRangeException();
m_chTypeID = chTypeID;
m_strAlph = string.Empty;
m_nChars = nChars;
m_chFirst = char.MinValue;
m_chLast = char.MinValue;
m_dblCharSize = Log2(m_nChars);
}
public bool Contains(char ch)
{
if(m_chLast != char.MinValue)
return ((ch >= m_chFirst) && (ch <= m_chLast));
Debug.Assert(m_strAlph.Length > 0); // Don't call for catch-none set
return (m_strAlph.IndexOf(ch) >= 0);
}
}
private sealed class EntropyEncoder
{
private readonly string m_strAlph;
private Dictionary<char, ulong> m_dHisto = new Dictionary<char, ulong>();
private readonly ulong m_uBaseWeight;
private readonly ulong m_uCharWeight;
private readonly ulong m_uOccExclThreshold;
public EntropyEncoder(string strAlphabet, ulong uBaseWeight,
ulong uCharWeight, ulong uOccExclThreshold)
{
if(strAlphabet == null) throw new ArgumentNullException();
if(strAlphabet.Length == 0) throw new ArgumentException();
m_strAlph = strAlphabet;
m_uBaseWeight = uBaseWeight;
m_uCharWeight = uCharWeight;
m_uOccExclThreshold = uOccExclThreshold;
#if DEBUG
Dictionary<char, bool> d = new Dictionary<char, bool>();
foreach(char ch in m_strAlph) { d[ch] = true; }
Debug.Assert(d.Count == m_strAlph.Length); // No duplicates
#endif
}
public void Reset()
{
m_dHisto.Clear();
}
public void Write(char ch)
{
Debug.Assert(m_strAlph.IndexOf(ch) >= 0);
ulong uOcc;
m_dHisto.TryGetValue(ch, out uOcc);
Debug.Assert(m_dHisto.ContainsKey(ch) || (uOcc == 0));
m_dHisto[ch] = uOcc + 1;
}
public double GetOutputSize()
{
ulong uTotalWeight = m_uBaseWeight * (ulong)m_strAlph.Length;
foreach(ulong u in m_dHisto.Values)
{
Debug.Assert(u >= 1);
if(u > m_uOccExclThreshold)
uTotalWeight += (u - m_uOccExclThreshold) * m_uCharWeight;
}
double dSize = 0.0, dTotalWeight = (double)uTotalWeight;
foreach(ulong u in m_dHisto.Values)
{
ulong uWeight = m_uBaseWeight;
if(u > m_uOccExclThreshold)
uWeight += (u - m_uOccExclThreshold) * m_uCharWeight;
dSize -= (double)u * Log2((double)uWeight / dTotalWeight);
}
return dSize;
}
}
private sealed class MultiEntropyEncoder
{
private Dictionary<char, EntropyEncoder> m_dEncs =
new Dictionary<char, EntropyEncoder>();
public MultiEntropyEncoder()
{
}
public void AddEncoder(char chTypeID, EntropyEncoder ec)
{
if(ec == null) { Debug.Assert(false); return; }
Debug.Assert(!m_dEncs.ContainsKey(chTypeID));
m_dEncs[chTypeID] = ec;
}
public void Reset()
{
foreach(EntropyEncoder ec in m_dEncs.Values) { ec.Reset(); }
}
public bool Write(char chTypeID, char chData)
{
EntropyEncoder ec;
if(!m_dEncs.TryGetValue(chTypeID, out ec))
return false;
ec.Write(chData);
return true;
}
public double GetOutputSize()
{
double d = 0.0;
foreach(EntropyEncoder ec in m_dEncs.Values)
{
d += ec.GetOutputSize();
}
return d;
}
}
private sealed class QePatternInstance
{
private readonly int m_iPos;
public int Position { get { return m_iPos; } }
private readonly int m_nLen;
public int Length { get { return m_nLen; } }
private readonly char m_chPatternID;
public char PatternID { get { return m_chPatternID; } }
private readonly double m_dblCost;
public double Cost { get { return m_dblCost; } }
private readonly QeCharType m_ctSingle;
public QeCharType SingleCharType { get { return m_ctSingle; } }
public QePatternInstance(int iPosition, int nLength, char chPatternID,
double dblCost)
{
m_iPos = iPosition;
m_nLen = nLength;
m_chPatternID = chPatternID;
m_dblCost = dblCost;
m_ctSingle = null;
}
public QePatternInstance(int iPosition, int nLength, QeCharType ctSingle)
{
m_iPos = iPosition;
m_nLen = nLength;
m_chPatternID = ctSingle.TypeID;
m_dblCost = ctSingle.CharSize;
m_ctSingle = ctSingle;
}
}
private sealed class QePathState
{
public readonly int Position;
public readonly List<QePatternInstance> Path;
public QePathState(int iPosition, List<QePatternInstance> lPath)
{
this.Position = iPosition;
this.Path = lPath;
}
}
private static object m_objSyncInit = new object();
private static List<QeCharType> m_lCharTypes = null;
private static void EnsureInitialized()
{
lock(m_objSyncInit)
{
if(m_lCharTypes == null)
{
string strSpecial = PwCharSet.PrintableAsciiSpecial;
if(strSpecial.IndexOf(' ') >= 0) { Debug.Assert(false); }
else strSpecial = strSpecial + " ";
int nSp = strSpecial.Length;
int nHi = PwCharSet.HighAnsiChars.Length;
m_lCharTypes = new List<QeCharType>();
m_lCharTypes.Add(new QeCharType(PatternID.LowerAlpha,
PwCharSet.LowerCase, true));
m_lCharTypes.Add(new QeCharType(PatternID.UpperAlpha,
PwCharSet.UpperCase, true));
m_lCharTypes.Add(new QeCharType(PatternID.Digit,
PwCharSet.Digits, true));
m_lCharTypes.Add(new QeCharType(PatternID.Special,
strSpecial, false));
m_lCharTypes.Add(new QeCharType(PatternID.High,
PwCharSet.HighAnsiChars, false));
m_lCharTypes.Add(new QeCharType(PatternID.Other,
0x10000 - (2 * 26) - 10 - nSp - nHi));
}
}
} }
/// <summary> /// <summary>
@@ -46,84 +320,95 @@ namespace ModernKeePassLib.Cryptography
/// </summary> /// </summary>
/// <param name="vPasswordChars">Password to check.</param> /// <param name="vPasswordChars">Password to check.</param>
/// <returns>Estimated bit-strength of the password.</returns> /// <returns>Estimated bit-strength of the password.</returns>
/// <exception cref="System.ArgumentNullException">Thrown if the input
/// parameter is <c>null</c>.</exception>
public static uint EstimatePasswordBits(char[] vPasswordChars) public static uint EstimatePasswordBits(char[] vPasswordChars)
{ {
Debug.Assert(vPasswordChars != null); if(vPasswordChars == null) { Debug.Assert(false); return 0; }
if(vPasswordChars == null) throw new ArgumentNullException("vPasswordChars"); if(vPasswordChars.Length == 0) return 0;
bool bChLower = false, bChUpper = false, bChNumber = false; EnsureInitialized();
bool bChSpecial = false, bChHigh = false, bChControl = false;
Dictionary<char, uint> vCharCounts = new Dictionary<char, uint>();
Dictionary<int, uint> vDifferences = new Dictionary<int, uint>();
double dblEffectiveLength = 0.0;
for(int i = 0; i < vPasswordChars.Length; ++i) // Get character types int n = vPasswordChars.Length;
List<QePatternInstance>[] vPatterns = new List<QePatternInstance>[n];
for(int i = 0; i < n; ++i)
{ {
char tch = vPasswordChars[i]; vPatterns[i] = new List<QePatternInstance>();
if(tch < ' ') bChControl = true; QePatternInstance piChar = new QePatternInstance(i, 1,
else if((tch >= 'A') && (tch <= 'Z')) bChUpper = true; GetCharType(vPasswordChars[i]));
else if((tch >= 'a') && (tch <= 'z')) bChLower = true; vPatterns[i].Add(piChar);
else if((tch >= '0') && (tch <= '9')) bChNumber = true; }
else if((tch >= ' ') && (tch <= '/')) bChSpecial = true;
else if((tch >= ':') && (tch <= '@')) bChSpecial = true;
else if((tch >= '[') && (tch <= '`')) bChSpecial = true;
else if((tch >= '{') && (tch <= '~')) bChSpecial = true;
else if(tch > '~') bChHigh = true;
double dblDiffFactor = 1.0; FindRepetitions(vPasswordChars, vPatterns);
if(i >= 1) FindNumbers(vPasswordChars, vPatterns);
FindDiffSeqs(vPasswordChars, vPatterns);
FindPopularPasswords(vPasswordChars, vPatterns);
// Encoders must not be static, because the entropy estimation
// may run concurrently in multiple threads and the encoders are
// not read-only
EntropyEncoder ecPattern = new EntropyEncoder(PatternID.All, 0, 1, 0);
MultiEntropyEncoder mcData = new MultiEntropyEncoder();
for(int i = 0; i < (m_lCharTypes.Count - 1); ++i)
{
// Let m be the alphabet size. In order to ensure that two same
// characters cost at least as much as a single character, for
// the probability p and weight w of the character it must hold:
// -log(1/m) >= -2*log(p)
// <=> log(1/m) <= log(p^2) <=> 1/m <= p^2 <=> p >= sqrt(1/m);
// sqrt(1/m) = (1+w)/(m+w)
// <=> m+w = (1+w)*sqrt(m) <=> m+w = sqrt(m) + w*sqrt(m)
// <=> w*(1-sqrt(m)) = sqrt(m) - m <=> w = (sqrt(m)-m)/(1-sqrt(m))
// <=> w = (sqrt(m)-m)*(1+sqrt(m))/(1-m)
// <=> w = (sqrt(m)-m+m-m*sqrt(m))/(1-m) <=> w = sqrt(m)
ulong uw = (ulong)Math.Sqrt((double)m_lCharTypes[i].CharCount);
mcData.AddEncoder(m_lCharTypes[i].TypeID, new EntropyEncoder(
m_lCharTypes[i].Alphabet, 1, uw, 1));
}
double dblMinCost = (double)int.MaxValue;
int tStart = Environment.TickCount;
Stack<QePathState> sRec = new Stack<QePathState>();
sRec.Push(new QePathState(0, new List<QePatternInstance>()));
while(sRec.Count > 0)
{
int tDiff = Environment.TickCount - tStart;
if(tDiff > 500) break;
QePathState s = sRec.Pop();
if(s.Position >= n)
{ {
int iDiff = (int)tch - (int)vPasswordChars[i - 1]; Debug.Assert(s.Position == n);
uint uDiffCount; double dblCost = ComputePathCost(s.Path, vPasswordChars,
if(vDifferences.TryGetValue(iDiff, out uDiffCount)) ecPattern, mcData);
{ if(dblCost < dblMinCost) dblMinCost = dblCost;
++uDiffCount;
vDifferences[iDiff] = uDiffCount;
dblDiffFactor /= (double)uDiffCount;
}
else vDifferences.Add(iDiff, 1);
}
uint uCharCount;
if(vCharCounts.TryGetValue(tch, out uCharCount))
{
++uCharCount;
vCharCounts[tch] = uCharCount;
dblEffectiveLength += dblDiffFactor * (1.0 / (double)uCharCount);
} }
else else
{ {
vCharCounts.Add(tch, 1); List<QePatternInstance> lSubs = vPatterns[s.Position];
dblEffectiveLength += dblDiffFactor; for(int i = lSubs.Count - 1; i >= 0; --i)
{
QePatternInstance pi = lSubs[i];
Debug.Assert(pi.Position == s.Position);
Debug.Assert(pi.Length >= 1);
List<QePatternInstance> lNewPath =
new List<QePatternInstance>(s.Path.Count + 1);
lNewPath.AddRange(s.Path);
lNewPath.Add(pi);
Debug.Assert(lNewPath.Capacity == (s.Path.Count + 1));
QePathState sNew = new QePathState(s.Position +
pi.Length, lNewPath);
sRec.Push(sNew);
}
} }
} }
uint uCharSpace = 0; return (uint)Math.Ceiling(dblMinCost);
if(bChControl) uCharSpace += (uint)CharSpaceBits.Control;
if(bChUpper) uCharSpace += (uint)CharSpaceBits.Alpha;
if(bChLower) uCharSpace += (uint)CharSpaceBits.Alpha;
if(bChNumber) uCharSpace += (uint)CharSpaceBits.Number;
if(bChSpecial) uCharSpace += (uint)CharSpaceBits.Special;
if(bChHigh) uCharSpace += (uint)CharSpaceBits.High;
if(uCharSpace == 0) return 0;
double dblBitsPerChar = Math.Log((double)uCharSpace) / Math.Log(2.0);
double dblRating = dblBitsPerChar * dblEffectiveLength;
#if !KeePassLibSD
char[] vLowerCopy = new char[vPasswordChars.Length];
for(int ilc = 0; ilc < vLowerCopy.Length; ++ilc)
vLowerCopy[ilc] = char.ToLower(vPasswordChars[ilc]);
if(PopularPasswords.IsPopularPassword(vLowerCopy)) dblRating /= 8.0;
Array.Clear(vLowerCopy, 0, vLowerCopy.Length);
#endif
return (uint)Math.Ceiling(dblRating);
} }
/// <summary> /// <summary>
@@ -141,5 +426,343 @@ namespace ModernKeePassLib.Cryptography
return uResult; return uResult;
} }
private static QeCharType GetCharType(char ch)
{
int nTypes = m_lCharTypes.Count;
Debug.Assert((nTypes > 0) && (m_lCharTypes[nTypes - 1].CharCount > 256));
for(int i = 0; i < (nTypes - 1); ++i)
{
if(m_lCharTypes[i].Contains(ch))
return m_lCharTypes[i];
}
return m_lCharTypes[nTypes - 1];
}
private static double ComputePathCost(List<QePatternInstance> l,
char[] vPassword, EntropyEncoder ecPattern, MultiEntropyEncoder mcData)
{
ecPattern.Reset();
for(int i = 0; i < l.Count; ++i)
ecPattern.Write(l[i].PatternID);
double dblPatternCost = ecPattern.GetOutputSize();
mcData.Reset();
double dblDataCost = 0.0;
foreach(QePatternInstance pi in l)
{
QeCharType tChar = pi.SingleCharType;
if(tChar != null)
{
char ch = vPassword[pi.Position];
if(!mcData.Write(tChar.TypeID, ch))
dblDataCost += pi.Cost;
}
else dblDataCost += pi.Cost;
}
dblDataCost += mcData.GetOutputSize();
return (dblPatternCost + dblDataCost);
}
private static void FindPopularPasswords(char[] vPassword,
List<QePatternInstance>[] vPatterns)
{
int n = vPassword.Length;
char[] vLower = new char[n];
char[] vLeet = new char[n];
for(int i = 0; i < n; ++i)
{
char ch = vPassword[i];
vLower[i] = char.ToLower(ch);
vLeet[i] = char.ToLower(DecodeLeetChar(ch));
}
char chErased = default(char);
Debug.Assert(chErased == char.MinValue);
int nMaxLen = Math.Min(n, PopularPasswords.MaxLength);
for(int nSubLen = nMaxLen; nSubLen >= 3; --nSubLen)
{
if(!PopularPasswords.ContainsLength(nSubLen)) continue;
char[] vSub = new char[nSubLen];
for(int i = 0; i <= (n - nSubLen); ++i)
{
if(Array.IndexOf<char>(vLower, chErased, i, nSubLen) >= 0)
continue;
Array.Copy(vLower, i, vSub, 0, nSubLen);
if(!EvalAddPopularPasswordPattern(vPatterns, vPassword,
i, vSub, 0.0))
{
Array.Copy(vLeet, i, vSub, 0, nSubLen);
if(EvalAddPopularPasswordPattern(vPatterns, vPassword,
i, vSub, 1.5))
{
Array.Clear(vLower, i, nSubLen); // Not vLeet
Debug.Assert(vLower[i] == chErased);
}
}
else
{
Array.Clear(vLower, i, nSubLen);
Debug.Assert(vLower[i] == chErased);
}
}
}
}
private static bool EvalAddPopularPasswordPattern(List<QePatternInstance>[] vPatterns,
char[] vPassword, int i, char[] vSub, double dblCostPerMod)
{
ulong uDictSize;
if(!PopularPasswords.IsPopularPassword(vSub, out uDictSize))
return false;
int n = vSub.Length;
int d = HammingDist(vSub, 0, vPassword, i, n);
double dblCost = Log2((double)uDictSize);
// dblCost += log2(n binom d)
int k = Math.Min(d, n - d);
for(int j = n; j > (n - k); --j)
dblCost += Log2(j);
for(int j = k; j >= 2; --j)
dblCost -= Log2(j);
dblCost += dblCostPerMod * (double)d;
vPatterns[i].Add(new QePatternInstance(i, n, PatternID.Dictionary,
dblCost));
return true;
}
private static char DecodeLeetChar(char chLeet)
{
if((chLeet >= '\u00C0') && (chLeet <= '\u00C6')) return 'a';
if((chLeet >= '\u00C8') && (chLeet <= '\u00CB')) return 'e';
if((chLeet >= '\u00CC') && (chLeet <= '\u00CF')) return 'i';
if((chLeet >= '\u00D2') && (chLeet <= '\u00D6')) return 'o';
if((chLeet >= '\u00D9') && (chLeet <= '\u00DC')) return 'u';
if((chLeet >= '\u00E0') && (chLeet <= '\u00E6')) return 'a';
if((chLeet >= '\u00E8') && (chLeet <= '\u00EB')) return 'e';
if((chLeet >= '\u00EC') && (chLeet <= '\u00EF')) return 'i';
if((chLeet >= '\u00F2') && (chLeet <= '\u00F6')) return 'o';
if((chLeet >= '\u00F9') && (chLeet <= '\u00FC')) return 'u';
char ch;
switch(chLeet)
{
case '4':
case '@':
case '?':
case '^':
case '\u00AA': ch = 'a'; break;
case '8':
case '\u00DF': ch = 'b'; break;
case '(':
case '{':
case '[':
case '<':
case '\u00A2':
case '\u00A9':
case '\u00C7':
case '\u00E7': ch = 'c'; break;
case '\u00D0':
case '\u00F0': ch = 'd'; break;
case '3':
case '\u20AC':
case '&':
case '\u00A3': ch = 'e'; break;
case '6':
case '9': ch = 'g'; break;
case '#': ch = 'h'; break;
case '1':
case '!':
case '|':
case '\u00A1':
case '\u00A6': ch = 'i'; break;
case '\u00D1':
case '\u00F1': ch = 'n'; break;
case '0':
case '*':
case '\u00A4': // Currency
case '\u00B0': // Degree
case '\u00D8':
case '\u00F8': ch = 'o'; break;
case '\u00AE': ch = 'r'; break;
case '$':
case '5':
case '\u00A7': ch = 's'; break;
case '+':
case '7': ch = 't'; break;
case '\u00B5': ch = 'u'; break;
case '%':
case '\u00D7': ch = 'x'; break;
case '\u00A5':
case '\u00DD':
case '\u00FD':
case '\u00FF': ch = 'y'; break;
case '2': ch = 'z'; break;
default: ch = chLeet; break;
}
return ch;
}
private static int HammingDist(char[] v1, int iOffset1,
char[] v2, int iOffset2, int nLength)
{
int nDist = 0;
for(int i = 0; i < nLength; ++i)
{
if(v1[iOffset1 + i] != v2[iOffset2 + i]) ++nDist;
}
return nDist;
}
private static void FindRepetitions(char[] vPassword,
List<QePatternInstance>[] vPatterns)
{
int n = vPassword.Length;
char[] v = new char[n];
Array.Copy(vPassword, v, n);
char chErased = char.MaxValue;
for(int m = (n / 2); m >= 3; --m)
{
for(int x1 = 0; x1 <= (n - (2 * m)); ++x1)
{
bool bFoundRep = false;
for(int x2 = (x1 + m); x2 <= (n - m); ++x2)
{
if(PartsEqual(v, x1, x2, m))
{
double dblCost = Log2(x1 + 1) + Log2(m);
vPatterns[x2].Add(new QePatternInstance(x2, m,
PatternID.Repetition, dblCost));
ErasePart(v, x2, m, ref chErased);
bFoundRep = true;
}
}
if(bFoundRep) ErasePart(v, x1, m, ref chErased);
}
}
}
private static bool PartsEqual(char[] v, int x1, int x2, int nLength)
{
for(int i = 0; i < nLength; ++i)
{
if(v[x1 + i] != v[x2 + i]) return false;
}
return true;
}
private static void ErasePart(char[] v, int i, int n, ref char chErased)
{
for(int j = 0; j < n; ++j)
{
v[i + j] = chErased;
--chErased;
}
}
private static void FindNumbers(char[] vPassword,
List<QePatternInstance>[] vPatterns)
{
int n = vPassword.Length;
StringBuilder sb = new StringBuilder();
for(int i = 0; i < n; ++i)
{
char ch = vPassword[i];
if((ch >= '0') && (ch <= '9')) sb.Append(ch);
else
{
AddNumberPattern(vPatterns, sb.ToString(), i - sb.Length);
sb.Remove(0, sb.Length);
}
}
AddNumberPattern(vPatterns, sb.ToString(), n - sb.Length);
}
private static void AddNumberPattern(List<QePatternInstance>[] vPatterns,
string strNumber, int i)
{
if(strNumber.Length <= 2) return;
int nZeros = 0;
for(int j = 0; j < strNumber.Length; ++j)
{
if(strNumber[j] != '0') break;
++nZeros;
}
double dblCost = Log2(nZeros + 1);
if(nZeros < strNumber.Length)
{
string strNonZero = strNumber.Substring(nZeros);
#if KeePassLibSD
try { dblCost += Log2(double.Parse(strNonZero)); }
catch(Exception) { Debug.Assert(false); return; }
#else
double d;
if(double.TryParse(strNonZero, out d))
dblCost += Log2(d);
else { Debug.Assert(false); return; }
#endif
}
vPatterns[i].Add(new QePatternInstance(i, strNumber.Length,
PatternID.Number, dblCost));
}
private static void FindDiffSeqs(char[] vPassword,
List<QePatternInstance>[] vPatterns)
{
int d = int.MinValue, p = 0;
string str = new string(vPassword) + new string(char.MaxValue, 1);
for(int i = 1; i < str.Length; ++i)
{
int dCur = (int)str[i] - (int)str[i - 1];
if(dCur != d)
{
if((i - p) >= 3) // At least 3 chars involved
{
QeCharType ct = GetCharType(str[p]);
double dblCost = ct.CharSize + Log2(i - p - 1);
vPatterns[p].Add(new QePatternInstance(p,
i - p, PatternID.DiffSeq, dblCost));
}
d = dCur;
p = i - 1;
}
}
}
private static double Log2(double dblValue)
{
#if KeePassLibSD
return (Math.Log(dblValue) / Math.Log(2.0));
#else
return Math.Log(dblValue, 2.0);
#endif
}
} }
} }

View File

@@ -1,48 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using Windows.Storage.Streams;
namespace ModernKeePassLib.Cryptography
{
// Singleton adaptor that provides a part of the .net SHA256Managed class
class SHA256Managed
{
private static SHA256Managed instance;
private static HashAlgorithmProvider m_AlgProv;
private SHA256Managed()
{
String strAlgName = "SHA256";
m_AlgProv = HashAlgorithmProvider.OpenAlgorithm(strAlgName);
m_AlgProv.CreateHash();
}
public static SHA256Managed Instance
{
get
{
if (instance == null)
{
instance = new SHA256Managed();
}
return instance;
}
}
public byte[] ComputeHash(byte[] buffer )
{
IBuffer input = CryptographicBuffer.CreateFromByteArray( buffer);
IBuffer hashBuffer = m_AlgProv.HashData(input);
byte[] hash;
CryptographicBuffer.CopyToByteArray(hashBuffer, out hash);
return hash;
}
}
}

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -20,33 +20,38 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Security; using System.Security;
using Windows.Security.Cryptography.Core; #if PCL
using Windows.Security.Cryptography;
#else
using System.Security.Cryptography;
#endif
using System.Text;
using System.Globalization;
using System.Diagnostics;
using ModernKeePassLib.Cryptography.Cipher; using ModernKeePassLib.Cryptography.Cipher;
using ModernKeePassLib.Keys;
using ModernKeePassLib.Utility; using ModernKeePassLib.Utility;
using ModernKeePassLib.Resources; using ModernKeePassLib.Resources;
using Windows.Storage.Streams; using ModernKeePassLib.Security;
using Windows.Security.Cryptography;
namespace ModernKeePassLib.Cryptography namespace ModernKeePassLib.Cryptography
{ {
/* #pragma warning disable 1591 /* /// <summary>
/// <summary> /// Return values of the <c>SelfTest.Perform</c> method.
/// Return values of the <c>SelfTest.Perform</c> method. /// </summary>
/// </summary> public enum SelfTestResult
public enum SelfTestResult {
{ Success = 0,
Success = 0, RijndaelEcbError = 1,
RijndaelEcbError = 1, Salsa20Error = 2,
Salsa20Error = 2, NativeKeyTransformationError = 3
NativeKeyTransformationError = 3 } */
}
#pragma warning restore 1591 */
/// <summary> /// <summary>
/// Class containing self-test methods. /// Class containing self-test methods.
/// </summary> /// </summary>
public static class SelfTest public static class SelfTest
{ {
/// <summary> /// <summary>
/// Perform a self-test. /// Perform a self-test.
@@ -58,7 +63,9 @@ namespace ModernKeePassLib.Cryptography
TestRijndael(); TestRijndael();
TestSalsa20(); TestSalsa20();
#if !PCL
TestNativeKeyTransform(); TestNativeKeyTransform();
#endif
TestHmacOtp(); TestHmacOtp();
@@ -74,7 +81,7 @@ namespace ModernKeePassLib.Cryptography
internal static void TestFipsComplianceProblems() internal static void TestFipsComplianceProblems()
{ {
#if !KeePassWinRT #if !PCL && !KeePassRT
try { new RijndaelManaged(); } try { new RijndaelManaged(); }
catch(Exception exAes) catch(Exception exAes)
{ {
@@ -91,7 +98,7 @@ namespace ModernKeePassLib.Cryptography
private static void TestRijndael() private static void TestRijndael()
{ {
#if !PCL && !KeePassRT
// Test vector (official ECB test vector #356) // Test vector (official ECB test vector #356)
byte[] pbIV = new byte[16]; byte[] pbIV = new byte[16];
byte[] pbTestKey = new byte[32]; byte[] pbTestKey = new byte[32];
@@ -106,24 +113,6 @@ namespace ModernKeePassLib.Cryptography
for(i = 0; i < 16; ++i) pbTestData[i] = 0; for(i = 0; i < 16; ++i) pbTestData[i] = 0;
pbTestData[0] = 0x04; pbTestData[0] = 0x04;
String strAlgName = "AES_ECB"; // Algorithm name
IBuffer iv = null; // no IV used in ECB.
IBuffer buffMsg = CryptographicBuffer.CreateFromByteArray(pbTestData);
IBuffer keyMaterial = CryptographicBuffer.CreateFromByteArray(pbTestKey);
SymmetricKeyAlgorithmProvider objAlg = SymmetricKeyAlgorithmProvider.OpenAlgorithm(strAlgName);
CryptographicKey key = objAlg.CreateSymmetricKey(keyMaterial);
// Encrypt the data and return.
IBuffer buffEncrypt = CryptographicEngine.Encrypt(key, buffMsg, iv);
CryptographicBuffer.CopyToByteArray(buffEncrypt, out pbTestData);
if (!MemUtil.ArraysEqual(pbTestData, pbReferenceCT))
throw new SecurityException(KLRes.EncAlgorithmAes + ".");
#if false
RijndaelManaged r = new RijndaelManaged(); RijndaelManaged r = new RijndaelManaged();
if(r.BlockSize != 128) // AES block size if(r.BlockSize != 128) // AES block size
@@ -142,7 +131,6 @@ namespace ModernKeePassLib.Cryptography
if(!MemUtil.ArraysEqual(pbTestData, pbReferenceCT)) if(!MemUtil.ArraysEqual(pbTestData, pbReferenceCT))
throw new SecurityException(KLRes.EncAlgorithmAes + "."); throw new SecurityException(KLRes.EncAlgorithmAes + ".");
#endif #endif
} }
@@ -166,7 +154,7 @@ namespace ModernKeePassLib.Cryptography
Salsa20Cipher c = new Salsa20Cipher(pbKey, pbIV); Salsa20Cipher c = new Salsa20Cipher(pbKey, pbIV);
c.Encrypt(pb, pb.Length, false); c.Encrypt(pb, pb.Length, false);
if(!MemUtil.ArraysEqual(pb, pbExpected)) if(!MemUtil.ArraysEqual(pb, pbExpected))
throw new SecurityException("Salsa20."); throw new SecurityException("Salsa20-1");
#if DEBUG #if DEBUG
// Extended test in debug mode // Extended test in debug mode
@@ -183,13 +171,24 @@ namespace ModernKeePassLib.Cryptography
int nPos = Salsa20ToPos(c, r, pb.Length, 65536); int nPos = Salsa20ToPos(c, r, pb.Length, 65536);
c.Encrypt(pb, pb.Length, false); c.Encrypt(pb, pb.Length, false);
if(!MemUtil.ArraysEqual(pb, pbExpected2)) if(!MemUtil.ArraysEqual(pb, pbExpected2))
throw new SecurityException("Salsa20-2."); throw new SecurityException("Salsa20-2");
nPos = Salsa20ToPos(c, r, nPos + pb.Length, 131008); nPos = Salsa20ToPos(c, r, nPos + pb.Length, 131008);
Array.Clear(pb, 0, pb.Length); Array.Clear(pb, 0, pb.Length);
c.Encrypt(pb, pb.Length, true); c.Encrypt(pb, pb.Length, true);
if(!MemUtil.ArraysEqual(pb, pbExpected3)) if(!MemUtil.ArraysEqual(pb, pbExpected3))
throw new SecurityException("Salsa20-3."); throw new SecurityException("Salsa20-3");
Dictionary<string, bool> d = new Dictionary<string, bool>();
const int nRounds = 100;
for(int i = 0; i < nRounds; ++i)
{
byte[] z = new byte[32];
c = new Salsa20Cipher(z, BitConverter.GetBytes((long)i));
c.Encrypt(z, z.Length, true);
d[MemUtil.ByteArrayToHexString(z)] = true;
}
if(d.Count != nRounds) throw new SecurityException("Salsa20-4");
#endif #endif
} }
@@ -211,9 +210,10 @@ namespace ModernKeePassLib.Cryptography
} }
#endif #endif
#if !PCL
private static void TestNativeKeyTransform() private static void TestNativeKeyTransform()
{ {
#if DEBUG && TODO #if DEBUG
byte[] pbOrgKey = CryptoRandom.Instance.GetRandomBytes(32); byte[] pbOrgKey = CryptoRandom.Instance.GetRandomBytes(32);
byte[] pbSeed = CryptoRandom.Instance.GetRandomBytes(32); byte[] pbSeed = CryptoRandom.Instance.GetRandomBytes(32);
ulong uRounds = (ulong)((new Random()).Next(1, 0x3FFF)); ulong uRounds = (ulong)((new Random()).Next(1, 0x3FFF));
@@ -232,11 +232,12 @@ namespace ModernKeePassLib.Cryptography
throw new SecurityException("Native transform."); throw new SecurityException("Native transform.");
#endif #endif
} }
#endif
private static void TestMemUtil() private static void TestMemUtil()
{ {
#if DEBUG && !KeePassWinRT #if DEBUG
Random r = new Random(); Random r = new Random();
byte[] pb = CryptoRandom.Instance.GetRandomBytes((uint)r.Next( byte[] pb = CryptoRandom.Instance.GetRandomBytes((uint)r.Next(
0, 0x2FFFF)); 0, 0x2FFFF));
@@ -244,35 +245,64 @@ namespace ModernKeePassLib.Cryptography
if(!MemUtil.ArraysEqual(MemUtil.Decompress(pbCompressed), pb)) if(!MemUtil.ArraysEqual(MemUtil.Decompress(pbCompressed), pb))
throw new InvalidOperationException("GZip"); throw new InvalidOperationException("GZip");
pb = Encoding.ASCII.GetBytes("012345678901234567890a"); Encoding enc = StrUtil.Utf8;
byte[] pbN = Encoding.ASCII.GetBytes("9012"); pb = enc.GetBytes("012345678901234567890a");
byte[] pbN = enc.GetBytes("9012");
if(MemUtil.IndexOf<byte>(pb, pbN) != 9) if(MemUtil.IndexOf<byte>(pb, pbN) != 9)
throw new InvalidOperationException("MemUtil-1"); throw new InvalidOperationException("MemUtil-1");
pbN = Encoding.ASCII.GetBytes("01234567890123"); pbN = enc.GetBytes("01234567890123");
if(MemUtil.IndexOf<byte>(pb, pbN) != 0) if(MemUtil.IndexOf<byte>(pb, pbN) != 0)
throw new InvalidOperationException("MemUtil-2"); throw new InvalidOperationException("MemUtil-2");
pbN = Encoding.ASCII.GetBytes("a"); pbN = enc.GetBytes("a");
if(MemUtil.IndexOf<byte>(pb, pbN) != 21) if(MemUtil.IndexOf<byte>(pb, pbN) != 21)
throw new InvalidOperationException("MemUtil-3"); throw new InvalidOperationException("MemUtil-3");
pbN = Encoding.ASCII.GetBytes("0a"); pbN = enc.GetBytes("0a");
if(MemUtil.IndexOf<byte>(pb, pbN) != 20) if(MemUtil.IndexOf<byte>(pb, pbN) != 20)
throw new InvalidOperationException("MemUtil-4"); throw new InvalidOperationException("MemUtil-4");
pbN = Encoding.ASCII.GetBytes("1"); pbN = enc.GetBytes("1");
if(MemUtil.IndexOf<byte>(pb, pbN) != 1) if(MemUtil.IndexOf<byte>(pb, pbN) != 1)
throw new InvalidOperationException("MemUtil-5"); throw new InvalidOperationException("MemUtil-5");
pbN = Encoding.ASCII.GetBytes("b"); pbN = enc.GetBytes("b");
if(MemUtil.IndexOf<byte>(pb, pbN) >= 0) if(MemUtil.IndexOf<byte>(pb, pbN) >= 0)
throw new InvalidOperationException("MemUtil-6"); throw new InvalidOperationException("MemUtil-6");
pbN = Encoding.ASCII.GetBytes("012b"); pbN = enc.GetBytes("012b");
if(MemUtil.IndexOf<byte>(pb, pbN) >= 0) if(MemUtil.IndexOf<byte>(pb, pbN) >= 0)
throw new InvalidOperationException("MemUtil-7"); throw new InvalidOperationException("MemUtil-7");
byte[] pbRes = MemUtil.ParseBase32("MY======");
byte[] pbExp = Encoding.UTF8.GetBytes("f");
if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-1");
pbRes = MemUtil.ParseBase32("MZXQ====");
pbExp = Encoding.UTF8.GetBytes("fo");
if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-2");
pbRes = MemUtil.ParseBase32("MZXW6===");
pbExp = Encoding.UTF8.GetBytes("foo");
if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-3");
pbRes = MemUtil.ParseBase32("MZXW6YQ=");
pbExp = Encoding.UTF8.GetBytes("foob");
if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-4");
pbRes = MemUtil.ParseBase32("MZXW6YTB");
pbExp = Encoding.UTF8.GetBytes("fooba");
if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-5");
pbRes = MemUtil.ParseBase32("MZXW6YTBOI======");
pbExp = Encoding.UTF8.GetBytes("foobar");
if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-6");
pbRes = MemUtil.ParseBase32("JNSXSIDQOJXXM2LEMVZCAYTBONSWIIDPNYQG63TFFV2GS3LFEBYGC43TO5XXEZDTFY======");
pbExp = Encoding.UTF8.GetBytes("Key provider based on one-time passwords.");
if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-7");
#endif #endif
} }
private static void TestHmacOtp() private static void TestHmacOtp()
{ {
#if (DEBUG && !KeePassLibSD && TODO) #if (DEBUG && !KeePassLibSD && !KeePassRT)
byte[] pbSecret = Encoding.ASCII.GetBytes("12345678901234567890"); byte[] pbSecret = StrUtil.Utf8.GetBytes("12345678901234567890");
string[] vExp = new string[]{ "755224", "287082", "359152", string[] vExp = new string[]{ "755224", "287082", "359152",
"969429", "338314", "254676", "287922", "162583", "399871", "969429", "338314", "254676", "287922", "162583", "399871",
"520489" }; "520489" };
@@ -287,10 +317,10 @@ namespace ModernKeePassLib.Cryptography
private static void TestProtectedObjects() private static void TestProtectedObjects()
{ {
#if TODO
#if DEBUG #if DEBUG
byte[] pbData = Encoding.UTF8.GetBytes("Test Test Test Test"); Encoding enc = StrUtil.Utf8;
byte[] pbData = enc.GetBytes("Test Test Test Test");
ProtectedBinary pb = new ProtectedBinary(true, pbData); ProtectedBinary pb = new ProtectedBinary(true, pbData);
if(!pb.IsProtected) throw new SecurityException("ProtectedBinary-1"); if(!pb.IsProtected) throw new SecurityException("ProtectedBinary-1");
@@ -299,8 +329,8 @@ namespace ModernKeePassLib.Cryptography
throw new SecurityException("ProtectedBinary-2"); throw new SecurityException("ProtectedBinary-2");
if(!pb.IsProtected) throw new SecurityException("ProtectedBinary-3"); if(!pb.IsProtected) throw new SecurityException("ProtectedBinary-3");
byte[] pbData2 = Encoding.UTF8.GetBytes("Test Test Test Test"); byte[] pbData2 = enc.GetBytes("Test Test Test Test");
byte[] pbData3 = Encoding.UTF8.GetBytes("Test Test Test Test Test"); byte[] pbData3 = enc.GetBytes("Test Test Test Test Test");
ProtectedBinary pb2 = new ProtectedBinary(true, pbData2); ProtectedBinary pb2 = new ProtectedBinary(true, pbData2);
ProtectedBinary pb3 = new ProtectedBinary(true, pbData3); ProtectedBinary pb3 = new ProtectedBinary(true, pbData3);
if(!pb.Equals(pb2)) throw new SecurityException("ProtectedBinary-4"); if(!pb.Equals(pb2)) throw new SecurityException("ProtectedBinary-4");
@@ -323,8 +353,7 @@ namespace ModernKeePassLib.Cryptography
throw new SecurityException("ProtectedString-3"); throw new SecurityException("ProtectedString-3");
ps = new ProtectedString(true, "Test"); ps = new ProtectedString(true, "Test");
ProtectedString ps2 = new ProtectedString(true, ProtectedString ps2 = new ProtectedString(true, enc.GetBytes("Test"));
StrUtil.Utf8.GetBytes("Test"));
if(ps.IsEmpty) throw new SecurityException("ProtectedString-4"); if(ps.IsEmpty) throw new SecurityException("ProtectedString-4");
pbData = ps.ReadUtf8(); pbData = ps.ReadUtf8();
pbData2 = ps2.ReadUtf8(); pbData2 = ps2.ReadUtf8();
@@ -340,7 +369,41 @@ namespace ModernKeePassLib.Cryptography
throw new SecurityException("ProtectedString-8"); throw new SecurityException("ProtectedString-8");
if(!ps.IsProtected) throw new SecurityException("ProtectedString-9"); if(!ps.IsProtected) throw new SecurityException("ProtectedString-9");
if(!ps2.IsProtected) throw new SecurityException("ProtectedString-10"); if(!ps2.IsProtected) throw new SecurityException("ProtectedString-10");
#endif
Random r = new Random();
string str = string.Empty;
ps = new ProtectedString();
for(int i = 0; i < 100; ++i)
{
bool bProt = ((r.Next() % 4) != 0);
ps = ps.WithProtection(bProt);
int x = r.Next(str.Length + 1);
int c = r.Next(20);
char ch = (char)r.Next(1, 256);
string strIns = new string(ch, c);
str = str.Insert(x, strIns);
ps = ps.Insert(x, strIns);
if(ps.IsProtected != bProt)
throw new SecurityException("ProtectedString-11");
if(ps.ReadString() != str)
throw new SecurityException("ProtectedString-12");
ps = ps.WithProtection(bProt);
x = r.Next(str.Length);
c = r.Next(str.Length - x + 1);
str = str.Remove(x, c);
ps = ps.Remove(x, c);
if(ps.IsProtected != bProt)
throw new SecurityException("ProtectedString-13");
if(ps.ReadString() != str)
throw new SecurityException("ProtectedString-14");
}
#endif #endif
} }
@@ -381,16 +444,64 @@ namespace ModernKeePassLib.Cryptography
throw new InvalidOperationException("StrUtil-V3"); throw new InvalidOperationException("StrUtil-V3");
if(StrUtil.VersionToString(0x00FF000000000000UL) != "255") if(StrUtil.VersionToString(0x00FF000000000000UL) != "255")
throw new InvalidOperationException("StrUtil-V4"); throw new InvalidOperationException("StrUtil-V4");
if(StrUtil.VersionToString(0x00FF000000000000UL, true) != "255.0") if(StrUtil.VersionToString(0x00FF000000000000UL, 2) != "255.0")
throw new InvalidOperationException("StrUtil-V5"); throw new InvalidOperationException("StrUtil-V5");
if(StrUtil.VersionToString(0x0000000000070000UL, true) != "0.0.7") if(StrUtil.VersionToString(0x0000000000070000UL) != "0.0.7")
throw new InvalidOperationException("StrUtil-V6"); throw new InvalidOperationException("StrUtil-V6");
if(StrUtil.VersionToString(0x0000000000000000UL) != "0")
throw new InvalidOperationException("StrUtil-V7");
if(StrUtil.VersionToString(0x00000000FFFF0000UL, 4) != "0.0.65535.0")
throw new InvalidOperationException("StrUtil-V8");
if(StrUtil.VersionToString(0x0000000000000000UL, 4) != "0.0.0.0")
throw new InvalidOperationException("StrUtil-V9");
if(StrUtil.RtfEncodeChar('\u0000') != "\\u0?")
throw new InvalidOperationException("StrUtil-Rtf1");
if(StrUtil.RtfEncodeChar('\u7FFF') != "\\u32767?")
throw new InvalidOperationException("StrUtil-Rtf2");
if(StrUtil.RtfEncodeChar('\u8000') != "\\u-32768?")
throw new InvalidOperationException("StrUtil-Rtf3");
if(StrUtil.RtfEncodeChar('\uFFFF') != "\\u-1?")
throw new InvalidOperationException("StrUtil-Rtf4");
if(!StrUtil.StringToBool(Boolean.TrueString))
throw new InvalidOperationException("StrUtil-Bool1");
if(StrUtil.StringToBool(Boolean.FalseString))
throw new InvalidOperationException("StrUtil-Bool2");
if(StrUtil.Count("Abracadabra", "a") != 4)
throw new InvalidOperationException("StrUtil-Count1");
if(StrUtil.Count("Bla", "U") != 0)
throw new InvalidOperationException("StrUtil-Count2");
if(StrUtil.Count("AAAAA", "AA") != 4)
throw new InvalidOperationException("StrUtil-Count3");
const string sU = "data:mytype;base64,";
if(!StrUtil.IsDataUri(sU))
throw new InvalidOperationException("StrUtil-DataUri1");
if(!StrUtil.IsDataUri(sU, "mytype"))
throw new InvalidOperationException("StrUtil-DataUri2");
if(StrUtil.IsDataUri(sU, "notmytype"))
throw new InvalidOperationException("StrUtil-DataUri3");
uint u = 0x7FFFFFFFU;
if(u.ToString(NumberFormatInfo.InvariantInfo) != "2147483647")
throw new InvalidOperationException("StrUtil-Inv1");
if(uint.MaxValue.ToString(NumberFormatInfo.InvariantInfo) !=
"4294967295")
throw new InvalidOperationException("StrUtil-Inv2");
if(long.MinValue.ToString(NumberFormatInfo.InvariantInfo) !=
"-9223372036854775808")
throw new InvalidOperationException("StrUtil-Inv3");
if(short.MinValue.ToString(NumberFormatInfo.InvariantInfo) !=
"-32768")
throw new InvalidOperationException("StrUtil-Inv4");
#endif #endif
} }
private static void TestUrlUtil() private static void TestUrlUtil()
{ {
#if DEBUG && TODO #if DEBUG
if(UrlUtil.GetHost(@"scheme://domain:port/path?query_string#fragment_id") != if(UrlUtil.GetHost(@"scheme://domain:port/path?query_string#fragment_id") !=
"domain") "domain")
throw new InvalidOperationException("UrlUtil-H1"); throw new InvalidOperationException("UrlUtil-H1");
@@ -408,7 +519,7 @@ namespace ModernKeePassLib.Cryptography
if(UrlUtil.GetHost(@"s://u:p@d.tld:p/p?q#f") != "d.tld") if(UrlUtil.GetHost(@"s://u:p@d.tld:p/p?q#f") != "d.tld")
throw new InvalidOperationException("UrlUtil-H7"); throw new InvalidOperationException("UrlUtil-H7");
if(NativeLib.IsUnix()) return; //if(NativeLib.IsUnix()) return;
string strBase = "\\\\HOMESERVER\\Apps\\KeePass\\KeePass.exe"; string strBase = "\\\\HOMESERVER\\Apps\\KeePass\\KeePass.exe";
string strDoc = "\\\\HOMESERVER\\Documents\\KeePass\\NewDatabase.kdbx"; string strDoc = "\\\\HOMESERVER\\Documents\\KeePass\\NewDatabase.kdbx";
@@ -419,6 +530,13 @@ namespace ModernKeePassLib.Cryptography
str = UrlUtil.MakeAbsolutePath(strBase, strRel); str = UrlUtil.MakeAbsolutePath(strBase, strRel);
if(!str.Equals(strDoc)) throw new InvalidOperationException("UrlUtil-R2"); if(!str.Equals(strDoc)) throw new InvalidOperationException("UrlUtil-R2");
str = UrlUtil.GetQuotedAppPath(" \"Test\" \"%1\" ");
if(str != "Test") throw new InvalidOperationException("UrlUtil-Q1");
str = UrlUtil.GetQuotedAppPath("C:\\Program Files\\Test.exe");
if(str != "C:\\Program Files\\Test.exe") throw new InvalidOperationException("UrlUtil-Q2");
str = UrlUtil.GetQuotedAppPath("Reg.exe \"Test\" \"Test 2\"");
if(str != "Reg.exe \"Test\" \"Test 2\"") throw new InvalidOperationException("UrlUtil-Q3");
#endif #endif
} }
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -39,18 +39,18 @@ namespace ModernKeePassLib.Interfaces
} }
/// <summary> /// <summary>
/// The date/time when the object was last accessed. /// The date/time when the object was last modified.
/// </summary> /// </summary>
DateTime LastAccessTime DateTime LastModificationTime
{ {
get; get;
set; set;
} }
/// <summary> /// <summary>
/// The date/time when the object was last modified. /// The date/time when the object was last accessed.
/// </summary> /// </summary>
DateTime LastModificationTime DateTime LastAccessTime
{ {
get; get;
set; set;

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -22,104 +22,105 @@ using System.Text;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Security.Cryptography.Core; using Windows.Security.Cryptography.Core;
using Windows.Security.ExchangeActiveSyncProvisioning;
#if PCL
using Windows.Security.Cryptography;
#else
using System.Security.Cryptography;
#endif
using ModernKeePassLib.Native;
using ModernKeePassLib.Resources; using ModernKeePassLib.Resources;
using ModernKeePassLib.Security; using ModernKeePassLib.Security;
using ModernKeePassLib.Utility; using ModernKeePassLib.Utility;
using System.Threading.Tasks;
using Windows.Security.Cryptography;
using Windows.Storage.Streams;
using ModernKeePassLib.Cryptography;
namespace ModernKeePassLib.Keys namespace ModernKeePassLib.Keys
{ {
/// <summary> /// <summary>
/// Represents a key. A key can be build up using several user key data sources /// Represents a key. A key can be build up using several user key data sources
/// like a password, a key file, the currently logged on user credentials, /// like a password, a key file, the currently logged on user credentials,
/// the current computer ID, etc. /// the current computer ID, etc.
/// </summary> /// </summary>
public sealed class CompositeKey public sealed class CompositeKey
{ {
private List<IUserKey> m_vUserKeys = new List<IUserKey>(); private List<IUserKey> m_vUserKeys = new List<IUserKey>();
/// <summary> /// <summary>
/// List of all user keys contained in the current composite key. /// List of all user keys contained in the current composite key.
/// </summary> /// </summary>
public IEnumerable<IUserKey> UserKeys public IEnumerable<IUserKey> UserKeys
{ {
get { return m_vUserKeys; } get { return m_vUserKeys; }
} }
public uint UserKeyCount public uint UserKeyCount
{ {
get { return (uint)m_vUserKeys.Count; } get { return (uint) m_vUserKeys.Count; }
} }
/// <summary> /// <summary>
/// Construct a new, empty key object. /// Construct a new, empty key object.
/// </summary> /// </summary>
public CompositeKey() public CompositeKey()
{ {
} }
// /// <summary> // /// <summary>
// /// Deconstructor, clears up the key. // /// Deconstructor, clears up the key.
// /// </summary> // /// </summary>
// ~CompositeKey() // ~CompositeKey()
// { // {
// Clear(); // Clear();
// } // }
// /// <summary> // /// <summary>
// /// Clears the key. This function also erases all previously stored // /// Clears the key. This function also erases all previously stored
// /// user key data objects. // /// user key data objects.
// /// </summary> // /// </summary>
// public void Clear() // public void Clear()
// { // {
// foreach(IUserKey pKey in m_vUserKeys) // foreach(IUserKey pKey in m_vUserKeys)
// pKey.Clear(); // pKey.Clear();
// m_vUserKeys.Clear(); // m_vUserKeys.Clear();
// } // }
/// <summary> /// <summary>
/// Add a user key. /// Add a user key.
/// </summary> /// </summary>
/// <param name="pKey">User key to add.</param> /// <param name="pKey">User key to add.</param>
public void AddUserKey(IUserKey pKey) public void AddUserKey(IUserKey pKey)
{ {
Debug.Assert(pKey != null); if(pKey == null) throw new ArgumentNullException("pKey"); Debug.Assert(pKey != null);
if (pKey == null) throw new ArgumentNullException("pKey");
m_vUserKeys.Add(pKey); m_vUserKeys.Add(pKey);
} }
/// <summary> /// <summary>
/// Remove a user key. /// Remove a user key.
/// </summary> /// </summary>
/// <param name="pKey">User key to remove.</param> /// <param name="pKey">User key to remove.</param>
/// <returns>Returns <c>true</c> if the key was removed successfully.</returns> /// <returns>Returns <c>true</c> if the key was removed successfully.</returns>
public bool RemoveUserKey(IUserKey pKey) public bool RemoveUserKey(IUserKey pKey)
{ {
Debug.Assert(pKey != null); if(pKey == null) throw new ArgumentNullException("pKey"); Debug.Assert(pKey != null);
if (pKey == null) throw new ArgumentNullException("pKey");
Debug.Assert(m_vUserKeys.IndexOf(pKey) >= 0); Debug.Assert(m_vUserKeys.IndexOf(pKey) >= 0);
return m_vUserKeys.Remove(pKey); return m_vUserKeys.Remove(pKey);
} }
/// <summary> #if !PCL && !KeePassRT /// <summary>
/// Test whether the composite key contains a specific type of /// Test whether the composite key contains a specific type of
/// user keys (password, key file, ...). If at least one user /// user keys (password, key file, ...). If at least one user
/// key of that type is present, the function returns <c>true</c>. /// key of that type is present, the function returns <c>true</c>.
/// </summary> /// </summary>
/// <param name="tUserKeyType">User key type.</param> /// <param name="tUserKeyType">User key type.</param>
/// <returns>Returns <c>true</c>, if the composite key contains /// <returns>Returns <c>true</c>, if the composite key contains
/// a user key of the specified type.</returns> /// a user key of the specified type.</returns>
public bool ContainsType(Type tUserKeyType) public bool ContainsType(Type tUserKeyType)
{ {
Debug.Assert(false, "not yet implemented");
return false;
#if TODO
Debug.Assert(tUserKeyType != null); Debug.Assert(tUserKeyType != null);
if(tUserKeyType == null) throw new ArgumentNullException("tUserKeyType"); if(tUserKeyType == null) throw new ArgumentNullException("tUserKeyType");
@@ -130,7 +131,6 @@ namespace ModernKeePassLib.Keys
} }
return false; return false;
#endif
} }
/// <summary> /// <summary>
@@ -141,10 +141,6 @@ namespace ModernKeePassLib.Keys
/// or <c>null</c> if no key of that type is found.</returns> /// or <c>null</c> if no key of that type is found.</returns>
public IUserKey GetUserKey(Type tUserKeyType) public IUserKey GetUserKey(Type tUserKeyType)
{ {
Debug.Assert(false, "not yet implemented");
return null;
#if TODO
Debug.Assert(tUserKeyType != null); Debug.Assert(tUserKeyType != null);
if(tUserKeyType == null) throw new ArgumentNullException("tUserKeyType"); if(tUserKeyType == null) throw new ArgumentNullException("tUserKeyType");
@@ -155,82 +151,94 @@ namespace ModernKeePassLib.Keys
} }
return null; return null;
}
#endif #endif
}
/// <summary> /// <summary>
/// Creates the composite key from the supplied user key sources (password, /// Creates the composite key from the supplied user key sources (password,
/// key file, user account, computer ID, etc.). /// key file, user account, computer ID, etc.).
/// </summary> /// </summary>
private byte[] CreateRawCompositeKey32() private byte[] CreateRawCompositeKey32()
{ {
ValidateUserKeys(); ValidateUserKeys();
// Concatenate user key data // Concatenate user key data
MemoryStream ms = new MemoryStream(); MemoryStream ms = new MemoryStream();
foreach(IUserKey pKey in m_vUserKeys) foreach (IUserKey pKey in m_vUserKeys)
{ {
ProtectedBinary b = pKey.KeyData; ProtectedBinary b = pKey.KeyData;
if(b != null) if (b != null)
{ {
byte[] pbKeyData = b.ReadData(); byte[] pbKeyData = b.ReadData();
ms.Write(pbKeyData, 0, pbKeyData.Length); ms.Write(pbKeyData, 0, pbKeyData.Length);
MemUtil.ZeroByteArray(pbKeyData); MemUtil.ZeroByteArray(pbKeyData);
} }
} }
byte[] pbHash = SHA256Managed.Instance.ComputeHash(ms.ToArray()); #if PCL
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
var pbHash = sha256.HashData(ms.ToArray().AsBuffer()).ToArray();
#else
SHA256Managed sha256 = new SHA256Managed();
byte[] pbHash = sha256.ComputeHash(ms.ToArray());
#endif
ms.Dispose();
return pbHash;
}
return pbHash; public bool EqualsValue(CompositeKey ckOther)
{
if (ckOther == null) throw new ArgumentNullException("ckOther");
} byte[] pbThis = CreateRawCompositeKey32();
byte[] pbOther = ckOther.CreateRawCompositeKey32();
bool bResult = MemUtil.ArraysEqual(pbThis, pbOther);
Array.Clear(pbOther, 0, pbOther.Length);
Array.Clear(pbThis, 0, pbThis.Length);
public bool EqualsValue(CompositeKey ckOther) return bResult;
{ }
if(ckOther == null) throw new ArgumentNullException("ckOther");
byte[] pbThis = CreateRawCompositeKey32(); /// <summary>
byte[] pbOther = ckOther.CreateRawCompositeKey32(); /// Generate a 32-bit wide key out of the composite key.
bool bResult = MemUtil.ArraysEqual(pbThis, pbOther); /// </summary>
Array.Clear(pbOther, 0, pbOther.Length); /// <param name="pbKeySeed32">Seed used in the key transformation
Array.Clear(pbThis, 0, pbThis.Length); /// rounds. Must be a byte array containing exactly 32 bytes; must
/// not be null.</param>
/// <param name="uNumRounds">Number of key transformation rounds.</param>
/// <returns>Returns a protected binary object that contains the
/// resulting 32-bit wide key.</returns>
public ProtectedBinary GenerateKey32(byte[] pbKeySeed32, ulong uNumRounds)
{
Debug.Assert(pbKeySeed32 != null);
if (pbKeySeed32 == null) throw new ArgumentNullException("pbKeySeed32");
Debug.Assert(pbKeySeed32.Length == 32);
if (pbKeySeed32.Length != 32) throw new ArgumentException("pbKeySeed32");
return bResult; byte[] pbRaw32 = CreateRawCompositeKey32();
} if ((pbRaw32 == null) || (pbRaw32.Length != 32))
{
Debug.Assert(false);
return null;
}
/// <summary> byte[] pbTrf32 = TransformKey(pbRaw32, pbKeySeed32, uNumRounds);
/// Generate a 32-bit wide key out of the composite key. if ((pbTrf32 == null) || (pbTrf32.Length != 32))
/// </summary> {
/// <param name="pbKeySeed32">Seed used in the key transformation Debug.Assert(false);
/// rounds. Must be a byte array containing exactly 32 bytes; must return null;
/// not be null.</param> }
/// <param name="uNumRounds">Number of key transformation rounds.</param>
/// <returns>Returns a protected binary object that contains the
/// resulting 32-bit wide key.</returns>
public ProtectedBinary GenerateKey32(byte[] pbKeySeed32, ulong uNumRounds)
{
Debug.Assert(pbKeySeed32 != null);
if(pbKeySeed32 == null) throw new ArgumentNullException("pbKeySeed32");
Debug.Assert(pbKeySeed32.Length == 32);
if(pbKeySeed32.Length != 32) throw new ArgumentException("pbKeySeed32");
byte[] pbRaw32 = CreateRawCompositeKey32(); ProtectedBinary pbRet = new ProtectedBinary(true, pbTrf32);
if((pbRaw32 == null) || (pbRaw32.Length != 32)) MemUtil.ZeroByteArray(pbTrf32);
{ Debug.Assert(false); return null; } MemUtil.ZeroByteArray(pbRaw32);
byte[] pbTrf32 = TransformKey(pbRaw32, pbKeySeed32, uNumRounds); return pbRet;
if((pbTrf32 == null) || (pbTrf32.Length != 32)) }
{ Debug.Assert(false); return null; }
ProtectedBinary pbRet = new ProtectedBinary(true, pbTrf32); private void ValidateUserKeys()
MemUtil.ZeroByteArray(pbTrf32); {
MemUtil.ZeroByteArray(pbRaw32); #if !PCL
return pbRet;
}
private void ValidateUserKeys()
{
int nAccounts = 0; int nAccounts = 0;
foreach(IUserKey uKey in m_vUserKeys) foreach(IUserKey uKey in m_vUserKeys)
@@ -244,98 +252,69 @@ namespace ModernKeePassLib.Keys
Debug.Assert(false); Debug.Assert(false);
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
} #endif
}
/// <summary> /// <summary>
/// Transform the current key <c>uNumRounds</c> times. /// Transform the current key <c>uNumRounds</c> times.
/// </summary> /// </summary>
/// <param name="pbOriginalKey32">The original key which will be transformed. /// <param name="pbOriginalKey32">The original key which will be transformed.
/// This parameter won't be modified.</param> /// This parameter won't be modified.</param>
/// <param name="pbKeySeed32">Seed used for key transformations. Must not /// <param name="pbKeySeed32">Seed used for key transformations. Must not
/// be <c>null</c>. This parameter won't be modified.</param> /// be <c>null</c>. This parameter won't be modified.</param>
/// <param name="uNumRounds">Transformation count.</param> /// <param name="uNumRounds">Transformation count.</param>
/// <returns>256-bit transformed key.</returns> /// <returns>256-bit transformed key.</returns>
private static byte[] TransformKey(byte[] pbOriginalKey32, byte[] pbKeySeed32, private static byte[] TransformKey(byte[] pbOriginalKey32, byte[] pbKeySeed32,
ulong uNumRounds) ulong uNumRounds)
{ {
Debug.Assert((pbOriginalKey32 != null) && (pbOriginalKey32.Length == 32));
if (pbOriginalKey32 == null) throw new ArgumentNullException("pbOriginalKey32");
if (pbOriginalKey32.Length != 32) throw new ArgumentException();
Debug.Assert((pbOriginalKey32 != null) && (pbOriginalKey32.Length == 32)); Debug.Assert((pbKeySeed32 != null) && (pbKeySeed32.Length == 32));
if(pbOriginalKey32 == null) throw new ArgumentNullException("pbOriginalKey32"); if (pbKeySeed32 == null) throw new ArgumentNullException("pbKeySeed32");
if(pbOriginalKey32.Length != 32) throw new ArgumentException(); if (pbKeySeed32.Length != 32) throw new ArgumentException();
Debug.Assert((pbKeySeed32 != null) && (pbKeySeed32.Length == 32)); byte[] pbNewKey = new byte[32];
if(pbKeySeed32 == null) throw new ArgumentNullException("pbKeySeed32"); Array.Copy(pbOriginalKey32, pbNewKey, pbNewKey.Length);
if(pbKeySeed32.Length != 32) throw new ArgumentException();
byte[] pbNewKey = new byte[32]; #if !PCL // Try to use the native library first
Array.Copy(pbOriginalKey32, pbNewKey, pbNewKey.Length); if(NativeLib.TransformKey256(pbNewKey, pbKeySeed32, uNumRounds))
return (new SHA256Managed()).ComputeHash(pbNewKey);
#endif
if(TransformKeyManaged(pbNewKey, pbKeySeed32, uNumRounds) == false) if (TransformKeyManaged(pbNewKey, pbKeySeed32, uNumRounds) == false)
return null; return null;
byte[] transformedKey = SHA256Managed.Instance.ComputeHash(pbNewKey); #if PCL
return (transformedKey); var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
} return sha256.HashData(pbNewKey.AsBuffer()).ToArray();
#else
SHA256Managed sha256 = new SHA256Managed();
return sha256.ComputeHash(pbNewKey);
#endif
}
public static bool TransformKeyManaged(byte[] pbNewKey32, byte[] pbKeySeed32, public static bool TransformKeyManaged(byte[] pbNewKey32, byte[] pbKeySeed32,
ulong uNumRounds) ulong uNumRounds)
{ {
#if KeePassRT
KeyParameter kp = new KeyParameter(pbKeySeed32);
AesEngine aes = new AesEngine();
aes.Init(true, kp);
byte[] pbIV = new byte[16]; for(ulong i = 0; i < uNumRounds; ++i)
Array.Clear(pbIV, 0, pbIV.Length);
String strAlgName = "AES_ECB"; // Algorithm name
IBuffer iv = null; // no IV used in ECB.
IBuffer buffMsg = CryptographicBuffer.CreateFromByteArray(pbNewKey32);
IBuffer keyMaterial = CryptographicBuffer.CreateFromByteArray(pbKeySeed32);
SymmetricKeyAlgorithmProvider objAlg = SymmetricKeyAlgorithmProvider.OpenAlgorithm(strAlgName);
CryptographicKey key = objAlg.CreateSymmetricKey(keyMaterial);
for (ulong i = 0; i < uNumRounds; ++i)
{
buffMsg = CryptographicEngine.Encrypt(key, buffMsg, iv);
}
byte[] newKey32;
CryptographicBuffer.CopyToByteArray(buffMsg, out newKey32);
newKey32.CopyTo(pbNewKey32,0);
return true;
}
/// <summary>
/// Benchmark the <c>TransformKey</c> method. Within
/// <paramref name="uMilliseconds"/> ms, random keys will be transformed
/// and the number of performed transformations are returned.
/// </summary>
/// <param name="uMilliseconds">Test duration in ms.</param>
/// <param name="uStep">Stepping.
/// <paramref name="uStep" /> should be a prime number. For fast processors
/// (PCs) a value of <c>3001</c> is recommended, for slower processors (PocketPC)
/// a value of <c>401</c> is recommended.</param>
/// <returns>Number of transformations performed in the specified
/// amount of time. Maximum value is <c>uint.MaxValue</c>.</returns>
public static ulong TransformKeyBenchmark(uint uMilliseconds, ulong uStep)
{
Debug.Assert(false, "not yet implemented");
return 0;
#if TODO
ulong uRounds;
// Try native method
if(NativeLib.TransformKeyBenchmark256(uMilliseconds, out uRounds))
return uRounds;
byte[] pbIV = new byte[16];
Array.Clear(pbIV, 0, pbIV.Length);
byte[] pbKey = new byte[32];
byte[] pbNewKey = new byte[32];
for(int i = 0; i < pbKey.Length; ++i)
{ {
pbKey[i] = (byte)i; aes.ProcessBlock(pbNewKey32, 0, pbNewKey32, 0);
pbNewKey[i] = (byte)i; aes.ProcessBlock(pbNewKey32, 16, pbNewKey32, 16);
} }
#elif PCL
var aes = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesEcb);
var key = aes.CreateSymmetricKey(pbKeySeed32.AsBuffer());
//var iCrypt = CryptographicEngine.CreateEncryptor(key);
#else
byte[] pbIV = new byte[16];
Array.Clear(pbIV, 0, pbIV.Length);
RijndaelManaged r = new RijndaelManaged(); RijndaelManaged r = new RijndaelManaged();
if(r.BlockSize != 128) // AES block size if(r.BlockSize != 128) // AES block size
@@ -347,56 +326,40 @@ namespace ModernKeePassLib.Keys
r.IV = pbIV; r.IV = pbIV;
r.Mode = CipherMode.ECB; r.Mode = CipherMode.ECB;
r.KeySize = 256; r.KeySize = 256;
r.Key = pbKey; r.Key = pbKeySeed32;
ICryptoTransform iCrypt = r.CreateEncryptor(); ICryptoTransform iCrypt = r.CreateEncryptor();
// !iCrypt.CanReuseTransform -- doesn't work with Mono
if((iCrypt == null) || (iCrypt.InputBlockSize != 16) ||
(iCrypt.OutputBlockSize != 16))
{
Debug.Assert(false, "Invalid ICryptoTransform.");
Debug.Assert(iCrypt.InputBlockSize == 16, "Invalid input block size!");
Debug.Assert(iCrypt.OutputBlockSize == 16, "Invalid output block size!");
return PwDefs.DefaultKeyEncryptionRounds;
}
DateTime dtStart = DateTime.Now;
TimeSpan ts;
double dblReqMillis = uMilliseconds;
uRounds = 0;
while(true)
{
for(ulong j = 0; j < uStep; ++j)
{
iCrypt.TransformBlock(pbNewKey, 0, 16, pbNewKey, 0);
iCrypt.TransformBlock(pbNewKey, 16, 16, pbNewKey, 16);
}
uRounds += uStep;
if(uRounds < uStep) // Overflow check
{
uRounds = ulong.MaxValue;
break;
}
ts = DateTime.Now - dtStart;
if(ts.TotalMilliseconds > dblReqMillis) break;
}
return uRounds;
#endif #endif
// !iCrypt.CanReuseTransform -- doesn't work with Mono
/*if ((iCrypt == null) || (iCrypt.InputBlockSize != 16) ||
(iCrypt.OutputBlockSize != 16))*/
if (aes.BlockLength != 16)
{
Debug.Assert(false, "Invalid ICryptoTransform.");
/*Debug.Assert((iCrypt.InputBlockSize == 16), "Invalid input block size!");
Debug.Assert((iCrypt.OutputBlockSize == 16), "Invalid output block size!");*/
Debug.Assert(aes.BlockLength == 16, "Invalid input block size!");
return false;
}
for (ulong i = 0; i < uNumRounds; ++i)
{
/*iCrypt.TransformBlock(pbNewKey32, 0, 16, pbNewKey32, 0);
iCrypt.TransformBlock(pbNewKey32, 16, 16, pbNewKey32, 16);*/
}
return true;
} }
} }
public sealed class InvalidCompositeKeyException : Exception public sealed class InvalidCompositeKeyException : Exception
{ {
public override string Message public override string Message
{ {
get get
{ {
return "The composite key is invalid!" + Environment.NewLine + "Make sure the composite key is correct and try again."; // No translation needed here, the message will not be shown in the UI. return KLRes.InvalidCompositeKey + Environment.NewLine
+ Environment.NewLine + KLRes.InvalidCompositeKeyHint;
} }
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -17,12 +17,24 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Security.Cryptography.Core;
#if PCL
using Windows.Security.Cryptography;
#else
using System.Security.Cryptography;
#endif
using ModernKeePassLib.Security; using ModernKeePassLib.Security;
using ModernKeePassLib.Utility;
namespace ModernKeePassLib.Keys namespace ModernKeePassLib.Keys
{ {
public sealed class KcpCustomKey : IUserKey public sealed class KcpCustomKey : IUserKey
{ {
private readonly string m_strName; private readonly string m_strName;
private ProtectedBinary m_pbKey; private ProtectedBinary m_pbKey;
@@ -42,10 +54,6 @@ namespace ModernKeePassLib.Keys
public KcpCustomKey(string strName, byte[] pbKeyData, bool bPerformHash) public KcpCustomKey(string strName, byte[] pbKeyData, bool bPerformHash)
{ {
Debug.Assert(false, "not yet implemented");
return;
#if TODO
Debug.Assert(strName != null); if(strName == null) throw new ArgumentNullException("strName"); Debug.Assert(strName != null); if(strName == null) throw new ArgumentNullException("strName");
Debug.Assert(pbKeyData != null); if(pbKeyData == null) throw new ArgumentNullException("pbKeyData"); Debug.Assert(pbKeyData != null); if(pbKeyData == null) throw new ArgumentNullException("pbKeyData");
@@ -53,12 +61,16 @@ namespace ModernKeePassLib.Keys
if(bPerformHash) if(bPerformHash)
{ {
#if PCL
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
var pbRaw = sha256.HashData(pbKeyData.AsBuffer());
#else
SHA256Managed sha256 = new SHA256Managed(); SHA256Managed sha256 = new SHA256Managed();
byte[] pbRaw = sha256.ComputeHash(pbKeyData); byte[] pbRaw = sha256.ComputeHash(pbKeyData);
m_pbKey = new ProtectedBinary(true, pbRaw); #endif
m_pbKey = new ProtectedBinary(true, pbRaw.ToArray());
} }
else m_pbKey = new ProtectedBinary(true, pbKeyData); else m_pbKey = new ProtectedBinary(true, pbKeyData);
#endif
} }
// public void Clear() // public void Clear()

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -17,16 +17,34 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
using System;
using System.Text;
using System.IO;
using System.Xml;
using System.Security;
#if PCL
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Windows.Security.Cryptography;
#else
using System.Security.Cryptography;
#endif
using System.Diagnostics;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Security.Cryptography.Core;
using ModernKeePassLib.Cryptography;
using ModernKeePassLib.Resources;
using ModernKeePassLib.Security; using ModernKeePassLib.Security;
using ModernKeePassLib.Serialization; using ModernKeePassLib.Serialization;
using ModernKeePassLib.Utility;
namespace ModernKeePassLib.Keys namespace ModernKeePassLib.Keys
{ {
/// <summary> /// <summary>
/// Key files as provided by the user. /// Key files as provided by the user.
/// </summary> /// </summary>
public sealed class KcpKeyFile : IUserKey public sealed class KcpKeyFile : IUserKey
{ {
private string m_strPath; private string m_strPath;
private ProtectedBinary m_pbKeyData; private ProtectedBinary m_pbKeyData;
@@ -51,22 +69,47 @@ namespace ModernKeePassLib.Keys
public KcpKeyFile(string strKeyFile) public KcpKeyFile(string strKeyFile)
{ {
Construct(IOConnectionInfo.FromPath(strKeyFile)); Construct(IOConnectionInfo.FromPath(strKeyFile), false);
}
public KcpKeyFile(string strKeyFile, bool bThrowIfDbFile)
{
Construct(IOConnectionInfo.FromPath(strKeyFile), bThrowIfDbFile);
} }
public KcpKeyFile(IOConnectionInfo iocKeyFile) public KcpKeyFile(IOConnectionInfo iocKeyFile)
{ {
Construct(iocKeyFile); Construct(iocKeyFile, false);
} }
private void Construct(IOConnectionInfo iocFile) public KcpKeyFile(IOConnectionInfo iocKeyFile, bool bThrowIfDbFile)
{
Construct(iocKeyFile, bThrowIfDbFile);
}
private void Construct(IOConnectionInfo iocFile, bool bThrowIfDbFile)
{ {
Debug.Assert(false, "not yet implemented");
return;
#if TODO
byte[] pbFileData = IOConnection.ReadFile(iocFile); byte[] pbFileData = IOConnection.ReadFile(iocFile);
if(pbFileData == null) throw new FileNotFoundException(); if(pbFileData == null) throw new FileNotFoundException();
if(bThrowIfDbFile && (pbFileData.Length >= 8))
{
uint uSig1 = MemUtil.BytesToUInt32(MemUtil.Mid(pbFileData, 0, 4));
uint uSig2 = MemUtil.BytesToUInt32(MemUtil.Mid(pbFileData, 4, 4));
if(((uSig1 == KdbxFile.FileSignature1) &&
(uSig2 == KdbxFile.FileSignature2)) ||
((uSig1 == KdbxFile.FileSignaturePreRelease1) &&
(uSig2 == KdbxFile.FileSignaturePreRelease2)) ||
((uSig1 == KdbxFile.FileSignatureOld1) &&
(uSig2 == KdbxFile.FileSignatureOld2)))
#if KeePassLibSD
throw new Exception(KLRes.KeyFileDbSel);
#else
throw new InvalidDataException(KLRes.KeyFileDbSel);
#endif
}
byte[] pbKey = LoadXmlKeyFile(pbFileData); byte[] pbKey = LoadXmlKeyFile(pbFileData);
if(pbKey == null) pbKey = LoadKeyFile(pbFileData); if(pbKey == null) pbKey = LoadKeyFile(pbFileData);
@@ -76,7 +119,6 @@ namespace ModernKeePassLib.Keys
m_pbKeyData = new ProtectedBinary(true, pbKey); m_pbKeyData = new ProtectedBinary(true, pbKey);
MemUtil.ZeroByteArray(pbKey); MemUtil.ZeroByteArray(pbKey);
#endif
} }
// public void Clear() // public void Clear()
@@ -87,9 +129,6 @@ namespace ModernKeePassLib.Keys
private static byte[] LoadKeyFile(byte[] pbFileData) private static byte[] LoadKeyFile(byte[] pbFileData)
{ {
Debug.Assert(false, "not yet implemented");
return null;
#if TODO
if(pbFileData == null) { Debug.Assert(false); return null; } if(pbFileData == null) { Debug.Assert(false); return null; }
int iLength = pbFileData.Length; int iLength = pbFileData.Length;
@@ -100,12 +139,16 @@ namespace ModernKeePassLib.Keys
if(pbKey == null) if(pbKey == null)
{ {
#if PCL
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
pbKey = sha256.HashData(pbFileData.AsBuffer()).ToArray();
#else
SHA256Managed sha256 = new SHA256Managed(); SHA256Managed sha256 = new SHA256Managed();
pbKey = sha256.ComputeHash(pbFileData); pbKey = sha256.ComputeHash(pbFileData);
#endif
} }
return pbKey; return pbKey;
#endif
} }
private static byte[] LoadBinaryKey32(byte[] pbFileData) private static byte[] LoadBinaryKey32(byte[] pbFileData)
@@ -118,15 +161,12 @@ namespace ModernKeePassLib.Keys
private static byte[] LoadHexKey32(byte[] pbFileData) private static byte[] LoadHexKey32(byte[] pbFileData)
{ {
Debug.Assert(false, "not yet implemented");
return null;
#if TODO
if(pbFileData == null) { Debug.Assert(false); return null; } if(pbFileData == null) { Debug.Assert(false); return null; }
if(pbFileData.Length != 64) { Debug.Assert(false); return null; } if(pbFileData.Length != 64) { Debug.Assert(false); return null; }
try try
{ {
string strHex = Encoding.ASCII.GetString(pbFileData, 0, 64); string strHex = StrUtil.Utf8.GetString(pbFileData, 0, 64);
if(!StrUtil.IsHexString(strHex, true)) return null; if(!StrUtil.IsHexString(strHex, true)) return null;
byte[] pbKey = MemUtil.HexStringToByteArray(strHex); byte[] pbKey = MemUtil.HexStringToByteArray(strHex);
@@ -138,7 +178,6 @@ namespace ModernKeePassLib.Keys
catch(Exception) { Debug.Assert(false); } catch(Exception) { Debug.Assert(false); }
return null; return null;
#endif
} }
/// <summary> /// <summary>
@@ -152,9 +191,6 @@ namespace ModernKeePassLib.Keys
/// <returns>Returns a <c>FileSaveResult</c> error code.</returns> /// <returns>Returns a <c>FileSaveResult</c> error code.</returns>
public static void Create(string strFilePath, byte[] pbAdditionalEntropy) public static void Create(string strFilePath, byte[] pbAdditionalEntropy)
{ {
Debug.Assert(false, "not yet implemented");
return;
#if TODO
byte[] pbKey32 = CryptoRandom.Instance.GetRandomBytes(32); byte[] pbKey32 = CryptoRandom.Instance.GetRandomBytes(32);
if(pbKey32 == null) throw new SecurityException(); if(pbKey32 == null) throw new SecurityException();
@@ -163,17 +199,22 @@ namespace ModernKeePassLib.Keys
pbFinalKey32 = pbKey32; pbFinalKey32 = pbKey32;
else else
{ {
MemoryStream ms = new MemoryStream(); using (MemoryStream ms = new MemoryStream())
ms.Write(pbAdditionalEntropy, 0, pbAdditionalEntropy.Length); {
ms.Write(pbKey32, 0, 32); ms.Write(pbAdditionalEntropy, 0, pbAdditionalEntropy.Length);
ms.Write(pbKey32, 0, 32);
SHA256Managed sha256 = new SHA256Managed(); #if PCL
pbFinalKey32 = sha256.ComputeHash(ms.ToArray()); var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
ms.Close(); pbFinalKey32 = sha256.HashData(ms.GetWindowsRuntimeBuffer()).ToArray();
#else
SHA256Managed sha256 = new SHA256Managed();
pbFinalKey32 = sha256.ComputeHash(ms.ToArray());
#endif
}
} }
CreateXmlKeyFile(strFilePath, pbFinalKey32); CreateXmlKeyFile(strFilePath, pbFinalKey32);
#endif
} }
// ================================================================ // ================================================================
@@ -199,9 +240,6 @@ namespace ModernKeePassLib.Keys
private static byte[] LoadXmlKeyFile(byte[] pbFileData) private static byte[] LoadXmlKeyFile(byte[] pbFileData)
{ {
Debug.Assert(false, "not yet implemented");
return null;
#if TODO
if(pbFileData == null) { Debug.Assert(false); return null; } if(pbFileData == null) { Debug.Assert(false); return null; }
MemoryStream ms = new MemoryStream(pbFileData, false); MemoryStream ms = new MemoryStream(pbFileData, false);
@@ -209,10 +247,38 @@ namespace ModernKeePassLib.Keys
try try
{ {
#if PCL
var doc = XDocument.Load(ms);
var el = doc.Root;
if((el == null) || !el.Name.LocalName.Equals(RootElementName))
return null;
if(el.DescendantNodes().Count() < 2)
return null;
foreach(var xmlChild in el.Descendants())
{
if(xmlChild.Name == MetaElementName) { } // Ignore Meta
else if(xmlChild.Name == KeyElementName)
{
foreach(var xmlKeyChild in xmlChild.Descendants())
{
if(xmlKeyChild.Name == KeyDataElementName)
{
if(pbKeyData == null)
pbKeyData = Convert.FromBase64String(xmlKeyChild.Value);
}
}
}
}
#else
XmlDocument doc = new XmlDocument(); XmlDocument doc = new XmlDocument();
doc.Load(ms); doc.Load(ms);
XmlElement el = doc.DocumentElement; XmlElement el = doc.DocumentElement;
if((el == null) || !el.Name.Equals(RootElementName)) return null; if((el == null) || !el.Name.Equals(RootElementName)) return null;
if(el.ChildNodes.Count < 2) return null; if(el.ChildNodes.Count < 2) return null;
@@ -231,26 +297,30 @@ namespace ModernKeePassLib.Keys
} }
} }
} }
#endif
} }
catch(Exception) { pbKeyData = null; } catch(Exception) { pbKeyData = null; }
finally { ms.Close(); } finally { ms.Dispose(); }
return pbKeyData; return pbKeyData;
#endif
} }
private static void CreateXmlKeyFile(string strFile, byte[] pbKeyData) private static void CreateXmlKeyFile(string strFile, byte[] pbKeyData)
{ {
Debug.Assert(false, "not yet implemented");
return;
#if TODO
Debug.Assert(strFile != null); Debug.Assert(strFile != null);
if(strFile == null) throw new ArgumentNullException("strFile"); if(strFile == null) throw new ArgumentNullException("strFile");
Debug.Assert(pbKeyData != null); Debug.Assert(pbKeyData != null);
if(pbKeyData == null) throw new ArgumentNullException("pbKeyData"); if(pbKeyData == null) throw new ArgumentNullException("pbKeyData");
XmlTextWriter xtw = new XmlTextWriter(strFile, StrUtil.Utf8); IOConnectionInfo ioc = IOConnectionInfo.FromPath(strFile);
Stream sOut = IOConnection.OpenWrite(ioc);
#if PCL
var settings = new XmlWriterSettings() { Encoding = StrUtil.Utf8 };
var xtw = XmlWriter.Create(sOut, settings);
#else
XmlTextWriter xtw = new XmlTextWriter(sOut, StrUtil.Utf8);
#endif
xtw.WriteStartDocument(); xtw.WriteStartDocument();
xtw.WriteWhitespace("\r\n"); xtw.WriteWhitespace("\r\n");
@@ -280,8 +350,9 @@ namespace ModernKeePassLib.Keys
xtw.WriteEndElement(); // RootElementName xtw.WriteEndElement(); // RootElementName
xtw.WriteWhitespace("\r\n"); xtw.WriteWhitespace("\r\n");
xtw.WriteEndDocument(); // End KeyFile xtw.WriteEndDocument(); // End KeyFile
xtw.Close(); xtw.Dispose();
#endif
} sOut.Dispose();
}
} }
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -18,17 +18,25 @@
*/ */
using System; using System;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Security.Cryptography.Core;
#if PCL
using Windows.Security.Cryptography;
#else
using System.Security.Cryptography;
#endif
using ModernKeePassLib.Security; using ModernKeePassLib.Security;
using ModernKeePassLib.Utility; using ModernKeePassLib.Utility;
using ModernKeePassLib.Cryptography;
namespace ModernKeePassLib.Keys namespace ModernKeePassLib.Keys
{ {
/// <summary> /// <summary>
/// Master password / passphrase as provided by the user. /// Master password / passphrase as provided by the user.
/// </summary> /// </summary>
public sealed class KcpPassword : IUserKey public sealed class KcpPassword : IUserKey
{ {
private ProtectedString m_psPassword; private ProtectedString m_psPassword;
private ProtectedBinary m_pbKeyData; private ProtectedBinary m_pbKeyData;
@@ -66,11 +74,16 @@ namespace ModernKeePassLib.Keys
Debug.Assert(pbPasswordUtf8 != null); Debug.Assert(pbPasswordUtf8 != null);
if(pbPasswordUtf8 == null) throw new ArgumentNullException("pbPasswordUtf8"); if(pbPasswordUtf8 == null) throw new ArgumentNullException("pbPasswordUtf8");
byte[] pbRaw = SHA256Managed.Instance.ComputeHash(pbPasswordUtf8); #if PCL
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
var pbRaw = sha256.HashData(pbPasswordUtf8.AsBuffer());
#else
SHA256Managed sha256 = new SHA256Managed();
byte[] pbRaw = sha256.ComputeHash(pbPasswordUtf8);
#endif
m_psPassword = new ProtectedString(true, pbPasswordUtf8); m_psPassword = new ProtectedString(true, pbPasswordUtf8);
m_pbKeyData = new ProtectedBinary(true, pbRaw); m_pbKeyData = new ProtectedBinary(true, pbRaw.ToArray());
} }
// public void Clear() // public void Clear()

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -17,15 +17,25 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
using System;
using System.Security;
using Windows.Security.Cryptography;
using System.IO;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Security.Cryptography.DataProtection;
using Windows.Storage;
using Windows.Storage.Streams;
using ModernKeePassLib.Cryptography;
using ModernKeePassLib.Resources;
using ModernKeePassLib.Security; using ModernKeePassLib.Security;
using ModernKeePassLib.Utility;
namespace ModernKeePassLib.Keys namespace ModernKeePassLib.Keys
{ {
/// <summary> /// <summary>
/// A user key depending on the currently logged on Windows user account. /// A user key depending on the currently logged on Windows user account.
/// </summary> /// </summary>
public sealed class KcpUserAccount : IUserKey public sealed class KcpUserAccount : IUserKey
{ {
private ProtectedBinary m_pbKeyData = null; private ProtectedBinary m_pbKeyData = null;
@@ -52,14 +62,14 @@ namespace ModernKeePassLib.Keys
/// </summary> /// </summary>
public KcpUserAccount() public KcpUserAccount()
{ {
Debug.Assert(false, "not yet implemented");
return;
#if TODO
// Test if ProtectedData is supported -- throws an exception // Test if ProtectedData is supported -- throws an exception
// when running on an old system (Windows 98 / ME). // when running on an old system (Windows 98 / ME).
byte[] pbDummyData = new byte[128]; byte[] pbDummyData = new byte[128];
ProtectedData.Protect(pbDummyData, m_pbEntropy,
DataProtectionScope.CurrentUser); DataProtectionProvider provider = new DataProtectionProvider("Local=user");
provider.ProtectAsync(pbDummyData.AsBuffer()).GetResults();
/*ProtectedData.Protect(pbDummyData, m_pbEntropy,
DataProtectionScope.CurrentUser);*/
byte[] pbKey = LoadUserKey(false); byte[] pbKey = LoadUserKey(false);
if(pbKey == null) pbKey = CreateUserKey(); if(pbKey == null) pbKey = CreateUserKey();
@@ -67,7 +77,6 @@ namespace ModernKeePassLib.Keys
m_pbKeyData = new ProtectedBinary(true, pbKey); m_pbKeyData = new ProtectedBinary(true, pbKey);
Array.Clear(pbKey, 0, pbKey.Length); Array.Clear(pbKey, 0, pbKey.Length);
#endif
} }
// public void Clear() // public void Clear()
@@ -77,42 +86,54 @@ namespace ModernKeePassLib.Keys
private static string GetUserKeyFilePath(bool bCreate) private static string GetUserKeyFilePath(bool bCreate)
{ {
Debug.Assert(false, "not yet implemented"); #if KeePassRT
return null; string strUserDir = ApplicationData.Current.RoamingFolder.Path;
#if TODO #else
/*string strUserDir = Environment.GetFolderPath(
string strUserDir = Environment.GetFolderPath( Environment.SpecialFolder.ApplicationData);*/
Environment.SpecialFolder.ApplicationData); var strUserDir = ApplicationData.Current.RoamingFolder.Path;
#endif
strUserDir = UrlUtil.EnsureTerminatingSeparator(strUserDir, false); strUserDir = UrlUtil.EnsureTerminatingSeparator(strUserDir, false);
strUserDir += PwDefs.ShortProductName; strUserDir += PwDefs.ShortProductName;
if(bCreate && !Directory.Exists(strUserDir)) // Folder is sure to exist
Directory.CreateDirectory(strUserDir); /*if(bCreate && !Directory.Exists(strUserDir))
Directory.CreateDirectory(strUserDir);*/
strUserDir = UrlUtil.EnsureTerminatingSeparator(strUserDir, false); strUserDir = UrlUtil.EnsureTerminatingSeparator(strUserDir, false);
return strUserDir + UserKeyFileName; return strUserDir + UserKeyFileName;
#endif
} }
private static byte[] LoadUserKey(bool bShowWarning) private static byte[] LoadUserKey(bool bShowWarning)
{ {
byte[] pbKey = null; byte[] pbKey = null;
#if !KeePassLibSD && TODO #if !KeePassLibSD
try try
{ {
string strFilePath = GetUserKeyFilePath(false); string strFilePath = GetUserKeyFilePath(false);
byte[] pbProtectedKey = File.ReadAllBytes(strFilePath); var pbProtectedKeyStream =
ApplicationData.Current.RoamingFolder.GetFileAsync(strFilePath).GetResults().
OpenAsync(FileAccessMode.Read).GetResults().AsStream();
using (var ms = new MemoryStream())
{
ms.CopyTo(pbProtectedKeyStream);
var pbProtectedKey = ms.ToArray();
pbKey = ProtectedData.Unprotect(pbProtectedKey, m_pbEntropy, //byte[] pbProtectedKey = File.ReadAllBytes(strFilePath);
DataProtectionScope.CurrentUser);
Array.Clear(pbProtectedKey, 0, pbProtectedKey.Length); DataProtectionProvider provider = new DataProtectionProvider("Local=user");
pbKey = provider.UnprotectAsync(pbProtectedKey.AsBuffer()).GetResults().ToArray();
/*pbKey = ProtectedData.Unprotect(pbProtectedKey, m_pbEntropy,
DataProtectionScope.CurrentUser);*/
Array.Clear(pbProtectedKey, 0, pbProtectedKey.Length);
}
} }
catch(Exception exLoad) catch(Exception exLoad)
{ {
if(bShowWarning) MessageService.ShowWarning(exLoad); //if(bShowWarning) MessageService.ShowWarning(exLoad);
pbKey = null; pbKey = null;
} }
@@ -125,16 +146,22 @@ namespace ModernKeePassLib.Keys
{ {
byte[] pbKey = null; byte[] pbKey = null;
#if !KeePassLibSD && TODO #if !KeePassLibSD
try try
{ {
string strFilePath = GetUserKeyFilePath(true); string strFilePath = GetUserKeyFilePath(true);
byte[] pbRandomKey = CryptoRandom.Instance.GetRandomBytes(64); byte[] pbRandomKey = CryptoRandom.Instance.GetRandomBytes(64);
byte[] pbProtectedKey = ProtectedData.Protect(pbRandomKey,
m_pbEntropy, DataProtectionScope.CurrentUser);
File.WriteAllBytes(strFilePath, pbProtectedKey); DataProtectionProvider provider = new DataProtectionProvider("Local=user");
var pbProtectedKey = provider.ProtectAsync(pbRandomKey.AsBuffer()).GetResults().ToArray();
/*byte[] pbProtectedKey = ProtectedData.Protect(pbRandomKey,
m_pbEntropy, DataProtectionScope.CurrentUser);*/
var file = ApplicationData.Current.RoamingFolder.CreateFileAsync(strFilePath).GetResults().
OpenAsync(FileAccessMode.ReadWrite).GetResults();
file.WriteAsync(pbProtectedKey.AsBuffer()).GetResults();
//File.WriteAllBytes(strFilePath, pbProtectedKey);
Array.Clear(pbProtectedKey, 0, pbProtectedKey.Length); Array.Clear(pbProtectedKey, 0, pbProtectedKey.Length);
Array.Clear(pbRandomKey, 0, pbRandomKey.Length); Array.Clear(pbRandomKey, 0, pbRandomKey.Length);

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

Binary file not shown.

View File

@@ -24,7 +24,7 @@
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath> <OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;NETSTANDARD1_2, KeePassWinRT</DefineConstants> <DefineConstants>TRACE;DEBUG;NETSTANDARD1_2, PCL</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
@@ -126,7 +126,6 @@
<Compile Include="Cryptography\PopularPasswords.cs" /> <Compile Include="Cryptography\PopularPasswords.cs" />
<Compile Include="Cryptography\QualityEstimation.cs" /> <Compile Include="Cryptography\QualityEstimation.cs" />
<Compile Include="Cryptography\SelfTest.cs" /> <Compile Include="Cryptography\SelfTest.cs" />
<Compile Include="Cryptography\SHA256Managed.cs" />
<Compile Include="DebugAssert.cs" /> <Compile Include="DebugAssert.cs" />
<Compile Include="Interfaces\IStructureItem.cs" /> <Compile Include="Interfaces\IStructureItem.cs" />
<Compile Include="Interfaces\IUIOperations.cs" /> <Compile Include="Interfaces\IUIOperations.cs" />
@@ -137,7 +136,6 @@
<Compile Include="Keys\KeyValidator.cs" /> <Compile Include="Keys\KeyValidator.cs" />
<Compile Include="Keys\KeyValidatorPool.cs" /> <Compile Include="Keys\KeyValidatorPool.cs" />
<Compile Include="Keys\UserKeyType.cs" /> <Compile Include="Keys\UserKeyType.cs" />
<Compile Include="Native\NativeMethods.cs" />
<Compile Include="PwCustomIcon.cs" /> <Compile Include="PwCustomIcon.cs" />
<Compile Include="Resources\KLRes.Generated.cs" /> <Compile Include="Resources\KLRes.Generated.cs" />
<Compile Include="Resources\KSRes.Generated.cs" /> <Compile Include="Resources\KSRes.Generated.cs" />
@@ -162,32 +160,22 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PwEnums.cs" /> <Compile Include="PwEnums.cs" />
<Compile Include="Serialization\BinaryReaderEx.cs" /> <Compile Include="Serialization\BinaryReaderEx.cs" />
<Compile Include="Serialization\CryptoStream.cs" />
<Compile Include="Serialization\FileLock.cs" /> <Compile Include="Serialization\FileLock.cs" />
<Compile Include="Serialization\FileTransactionEx.cs" /> <Compile Include="Serialization\FileTransactionEx.cs" />
<Compile Include="Serialization\HashedBlockStream.cs" /> <Compile Include="Serialization\HashedBlockStream.cs" />
<Compile Include="Serialization\IOConnection.cs" /> <Compile Include="Serialization\IOConnection.cs" />
<Compile Include="Serialization\Kdb4File.cs" />
<Compile Include="Serialization\Kdb4File.Read.cs" />
<Compile Include="Serialization\Kdb4File.Read.Streamed.cs" />
<Compile Include="Serialization\Kdb4File.Write.cs" />
<Compile Include="Serialization\IOConnectionInfo.cs" /> <Compile Include="Serialization\IOConnectionInfo.cs" />
<Compile Include="Serialization\KdbxFile.cs" />
<Compile Include="Serialization\KdbxFile.Read.cs" />
<Compile Include="Serialization\KdbxFile.Read.Streamed.cs" />
<Compile Include="Serialization\KdbxFile.Write.cs" />
<Compile Include="Serialization\OldFormatException.cs" /> <Compile Include="Serialization\OldFormatException.cs" />
<Compile Include="Translation\KPControlCustomization.cs" />
<Compile Include="Translation\KPFormCustomization.cs" />
<Compile Include="Translation\KPStringTable.cs" />
<Compile Include="Translation\KPStringTableItem.cs" />
<Compile Include="Translation\KPTranslation.cs" />
<Compile Include="Translation\KPTranslationProperties.cs" />
<Compile Include="Utility\AppLogEx.cs" /> <Compile Include="Utility\AppLogEx.cs" />
<Compile Include="Utility\MemUtil.cs" /> <Compile Include="Utility\MemUtil.cs" />
<Compile Include="Utility\MessageService.cs" />
<Compile Include="Native\NativeLib.cs" />
<Compile Include="Cryptography\PasswordGenerator\PwGenerator.cs" /> <Compile Include="Cryptography\PasswordGenerator\PwGenerator.cs" />
<Compile Include="Utility\StrUtil.cs" /> <Compile Include="Utility\StrUtil.cs" />
<Compile Include="Utility\UrlUtil.cs" /> <Compile Include="Utility\UrlUtil.cs" />
<Compile Include="Utility\TimeUtil.cs" /> <Compile Include="Utility\TimeUtil.cs" />
<Compile Include="WinRTColor.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="Libs\Windows.winmd" /> <None Include="Libs\Windows.winmd" />
@@ -201,6 +189,10 @@
<HintPath>Libs\Windows.winmd</HintPath> <HintPath>Libs\Windows.winmd</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Native\" />
<Folder Include="Translation\" />
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '12.0' "> <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '12.0' ">
<VisualStudioVersion>12.0</VisualStudioVersion> <VisualStudioVersion>12.0</VisualStudioVersion>
</PropertyGroup> </PropertyGroup>

View File

@@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp70</s:String></wpf:ResourceDictionary>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<ProjectView>ProjectFiles</ProjectView> <ProjectView>ShowAllFiles</ProjectView>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View File

@@ -0,0 +1,70 @@
using System;
using PlatformID = System.UInt32;
namespace KeePass2PCL.Native
{
internal static class NativeLib
{
public static ulong MonoVersion {
get { throw new NotImplementedException(); }
}
public static bool IsUnix()
{
return true;
}
}
internal static class NativeMethods
{
public static bool SupportsStrCmpNaturally {
get { throw new NotImplementedException(); }
}
public static int StrCmpNaturally (string s1, string s2)
{
throw new NotImplementedException();
}
}
internal 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,
SameLogon,
SameProcess
}
internal static class ProtectedMemory
{
public static byte[] Protect(byte[] userData, MemoryProtectionScope scope)
{
throw new NotImplementedException();
}
public static byte[] Unprotect(byte[] userData, MemoryProtectionScope scope)
{
throw new NotImplementedException();
}
}
}

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -19,7 +19,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Reflection;
using System.Diagnostics; using System.Diagnostics;
using ModernKeePassLib.Utility; using ModernKeePassLib.Utility;
@@ -44,6 +50,43 @@ namespace ModernKeePassLib.Native
set { m_bAllowNative = value; } set { m_bAllowNative = value; }
} }
private static ulong? m_ouMonoVersion = null;
public static ulong MonoVersion
{
get
{
if(m_ouMonoVersion.HasValue) return m_ouMonoVersion.Value;
ulong uVersion = 0;
try
{
Type t = Type.GetType("Mono.Runtime");
if(t != null)
{
MethodInfo mi = t.GetMethod("GetDisplayName",
BindingFlags.NonPublic | BindingFlags.Static);
if(mi != null)
{
string strName = (mi.Invoke(null, null) as string);
if(!string.IsNullOrEmpty(strName))
{
Match m = Regex.Match(strName, "\\d+(\\.\\d+)+");
if(m.Success)
uVersion = StrUtil.ParseVersion(m.Value);
else { Debug.Assert(false); }
}
else { Debug.Assert(false); }
}
else { Debug.Assert(false); }
}
}
catch(Exception) { Debug.Assert(false); }
m_ouMonoVersion = uVersion;
return uVersion;
}
}
/// <summary> /// <summary>
/// Determine if the native library is installed. /// Determine if the native library is installed.
/// </summary> /// </summary>
@@ -70,10 +113,6 @@ namespace ModernKeePassLib.Native
{ {
if(m_bIsUnix.HasValue) return m_bIsUnix.Value; if(m_bIsUnix.HasValue) return m_bIsUnix.Value;
#if KeePassWinRT
return false;
#else
PlatformID p = GetPlatformID(); PlatformID p = GetPlatformID();
// Mono defines Unix as 128 in early .NET versions // Mono defines Unix as 128 in early .NET versions
@@ -84,19 +123,20 @@ namespace ModernKeePassLib.Native
m_bIsUnix = (((int)p == 4) || ((int)p == 6) || ((int)p == 128)); m_bIsUnix = (((int)p == 4) || ((int)p == 6) || ((int)p == 128));
#endif #endif
return m_bIsUnix.Value; return m_bIsUnix.Value;
#endif //KeePassWinRT }
}
// TODO Bert : Not supported for the time being.
#if !KeePassWinRT
private static PlatformID? m_platID = null; private static PlatformID? m_platID = null;
public static PlatformID GetPlatformID() public static PlatformID GetPlatformID()
{ {
if(m_platID.HasValue) return m_platID.Value; if(m_platID.HasValue) return m_platID.Value;
#if KeePassRT
m_platID = PlatformID.Win32NT;
#else
m_platID = Environment.OSVersion.Platform; m_platID = Environment.OSVersion.Platform;
#endif
#if !KeePassLibSD #if (!KeePassLibSD && !KeePassRT)
// Mono returns PlatformID.Unix on Mac OS X, workaround this // Mono returns PlatformID.Unix on Mac OS X, workaround this
if(m_platID.Value == PlatformID.Unix) if(m_platID.Value == PlatformID.Unix)
{ {
@@ -108,11 +148,8 @@ namespace ModernKeePassLib.Native
return m_platID.Value; return m_platID.Value;
} }
#endif
#if (!KeePassLibSD && !KeePassRT)
// BERT Todo: Not supported for the moment.
#if !KeePassLibSD && TODO
public static string RunConsoleApp(string strAppPath, string strParams) public static string RunConsoleApp(string strAppPath, string strParams)
{ {
return RunConsoleApp(strAppPath, strParams, null); return RunConsoleApp(strAppPath, strParams, null);
@@ -120,40 +157,121 @@ namespace ModernKeePassLib.Native
public static string RunConsoleApp(string strAppPath, string strParams, public static string RunConsoleApp(string strAppPath, string strParams,
string strStdInput) string strStdInput)
{
return RunConsoleApp(strAppPath, strParams, strStdInput,
(AppRunFlags.GetStdOutput | AppRunFlags.WaitForExit));
}
private delegate string RunProcessDelegate();
public static string RunConsoleApp(string strAppPath, string strParams,
string strStdInput, AppRunFlags f)
{ {
if(strAppPath == null) throw new ArgumentNullException("strAppPath"); if(strAppPath == null) throw new ArgumentNullException("strAppPath");
if(strAppPath.Length == 0) throw new ArgumentException("strAppPath"); if(strAppPath.Length == 0) throw new ArgumentException("strAppPath");
try bool bStdOut = ((f & AppRunFlags.GetStdOutput) != AppRunFlags.None);
RunProcessDelegate fnRun = delegate()
{ {
ProcessStartInfo psi = new ProcessStartInfo(); try
psi.CreateNoWindow = true;
psi.FileName = strAppPath;
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
if(strStdInput != null) psi.RedirectStandardInput = true;
if(!string.IsNullOrEmpty(strParams)) psi.Arguments = strParams;
Process p = Process.Start(psi);
if(strStdInput != null)
{ {
p.StandardInput.Write(strStdInput); ProcessStartInfo psi = new ProcessStartInfo();
p.StandardInput.Close();
psi.CreateNoWindow = true;
psi.FileName = strAppPath;
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.UseShellExecute = false;
psi.RedirectStandardOutput = bStdOut;
if(strStdInput != null) psi.RedirectStandardInput = true;
if(!string.IsNullOrEmpty(strParams)) psi.Arguments = strParams;
Process p = Process.Start(psi);
if(strStdInput != null)
{
// Workaround for Mono Process StdIn BOM bug;
// https://sourceforge.net/p/keepass/bugs/1219/
EnsureNoBom(p.StandardInput);
p.StandardInput.Write(strStdInput);
p.StandardInput.Close();
}
string strOutput = string.Empty;
if(bStdOut) strOutput = p.StandardOutput.ReadToEnd();
if((f & AppRunFlags.WaitForExit) != AppRunFlags.None)
p.WaitForExit();
else if((f & AppRunFlags.GCKeepAlive) != AppRunFlags.None)
{
Thread th = new Thread(delegate()
{
try { p.WaitForExit(); }
catch(Exception) { Debug.Assert(false); }
});
th.Start();
}
return strOutput;
}
catch(Exception) { Debug.Assert(false); }
return null;
};
if((f & AppRunFlags.DoEvents) != AppRunFlags.None)
{
List<Form> lDisabledForms = new List<Form>();
if((f & AppRunFlags.DisableForms) != AppRunFlags.None)
{
foreach(Form form in Application.OpenForms)
{
if(!form.Enabled) continue;
lDisabledForms.Add(form);
form.Enabled = false;
}
} }
string strOutput = p.StandardOutput.ReadToEnd(); IAsyncResult ar = fnRun.BeginInvoke(null, null);
p.WaitForExit();
return strOutput; while(!ar.AsyncWaitHandle.WaitOne(0))
{
Application.DoEvents();
Thread.Sleep(2);
}
string strRet = fnRun.EndInvoke(ar);
for(int i = lDisabledForms.Count - 1; i >= 0; --i)
lDisabledForms[i].Enabled = true;
return strRet;
}
return fnRun();
}
private static void EnsureNoBom(StreamWriter sw)
{
if(sw == null) { Debug.Assert(false); return; }
if(!NativeLib.IsUnix()) return;
try
{
Encoding enc = sw.Encoding;
if(enc == null) { Debug.Assert(false); return; }
byte[] pbBom = enc.GetPreamble();
if((pbBom == null) || (pbBom.Length == 0)) return;
FieldInfo fi = typeof(StreamWriter).GetField("preamble_done",
BindingFlags.Instance | BindingFlags.NonPublic);
if(fi != null) fi.SetValue(sw, true);
} }
catch(Exception) { Debug.Assert(false); } catch(Exception) { Debug.Assert(false); }
return null;
} }
#endif #endif
@@ -172,12 +290,12 @@ namespace ModernKeePassLib.Native
KeyValuePair<IntPtr, IntPtr> kvp = PrepareArrays256(pBuf256, pKey256); KeyValuePair<IntPtr, IntPtr> kvp = PrepareArrays256(pBuf256, pKey256);
bool bResult = false; bool bResult = false;
/*try try
{ {
bResult = NativeMethods.TransformKey(kvp.Key, kvp.Value, uRounds); bResult = NativeMethods.TransformKey(kvp.Key, kvp.Value, uRounds);
} }
catch(Exception) { bResult = false; } catch(Exception) { bResult = false; }
*/
if(bResult) GetBuffers256(kvp, pBuf256, pKey256); if(bResult) GetBuffers256(kvp, pBuf256, pKey256);
NativeLib.FreeArrays(kvp); NativeLib.FreeArrays(kvp);
@@ -196,8 +314,8 @@ namespace ModernKeePassLib.Native
if(m_bAllowNative == false) return false; if(m_bAllowNative == false) return false;
/*try { puRounds = NativeMethods.TransformKeyBenchmark(uTimeMs); } try { puRounds = NativeMethods.TransformKeyBenchmark(uTimeMs); }
catch(Exception) { return false; }*/ catch(Exception) { return false; }
return true; return true;
} }

View File

@@ -0,0 +1,112 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Diagnostics;
namespace KeePass2PCL.Native
{
internal static partial class NativeMethods
{
#if (!KeePassLibSD && !KeePassRT)
[StructLayout(LayoutKind.Sequential)]
private struct XClassHint
{
public IntPtr res_name;
public IntPtr res_class;
}
[DllImport("libX11")]
private static extern int XSetClassHint(IntPtr display, IntPtr window, IntPtr class_hints);
private static Type m_tXplatUIX11 = null;
private static Type GetXplatUIX11Type(bool bThrowOnError)
{
if(m_tXplatUIX11 == null)
{
// CheckState is in System.Windows.Forms
string strTypeCS = typeof(CheckState).AssemblyQualifiedName;
string strTypeX11 = strTypeCS.Replace("CheckState", "XplatUIX11");
m_tXplatUIX11 = Type.GetType(strTypeX11, bThrowOnError, true);
}
return m_tXplatUIX11;
}
private static Type m_tHwnd = null;
private static Type GetHwndType(bool bThrowOnError)
{
if(m_tHwnd == null)
{
// CheckState is in System.Windows.Forms
string strTypeCS = typeof(CheckState).AssemblyQualifiedName;
string strTypeHwnd = strTypeCS.Replace("CheckState", "Hwnd");
m_tHwnd = Type.GetType(strTypeHwnd, bThrowOnError, true);
}
return m_tHwnd;
}
internal static void SetWmClass(Form f, string strName, string strClass)
{
if(f == null) { Debug.Assert(false); return; }
// The following crashes under Mac OS X (SIGSEGV in native code,
// not just an exception), thus skip it when we're on Mac OS X;
// https://sourceforge.net/projects/keepass/forums/forum/329221/topic/5860588
if(NativeLib.GetPlatformID() == PlatformID.MacOSX) return;
try
{
Type tXplatUIX11 = GetXplatUIX11Type(true);
FieldInfo fiDisplayHandle = tXplatUIX11.GetField("DisplayHandle",
BindingFlags.NonPublic | BindingFlags.Static);
IntPtr hDisplay = (IntPtr)fiDisplayHandle.GetValue(null);
Type tHwnd = GetHwndType(true);
MethodInfo miObjectFromHandle = tHwnd.GetMethod("ObjectFromHandle",
BindingFlags.Public | BindingFlags.Static);
object oHwnd = miObjectFromHandle.Invoke(null, new object[] { f.Handle });
FieldInfo fiWholeWindow = tHwnd.GetField("whole_window",
BindingFlags.NonPublic | BindingFlags.Instance);
IntPtr hWindow = (IntPtr)fiWholeWindow.GetValue(oHwnd);
XClassHint xch = new XClassHint();
xch.res_name = Marshal.StringToCoTaskMemAnsi(strName ?? string.Empty);
xch.res_class = Marshal.StringToCoTaskMemAnsi(strClass ?? string.Empty);
IntPtr pXch = Marshal.AllocCoTaskMem(Marshal.SizeOf(xch));
Marshal.StructureToPtr(xch, pXch, false);
XSetClassHint(hDisplay, hWindow, pXch);
Marshal.FreeCoTaskMem(pXch);
Marshal.FreeCoTaskMem(xch.res_name);
Marshal.FreeCoTaskMem(xch.res_class);
}
catch(Exception) { Debug.Assert(false); }
}
#endif
}
}

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -21,13 +21,20 @@ using System;
using System.Text; using System.Text;
using System.Security; using System.Security;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.IO;
using System.Diagnostics;
using ModernKeePassLib.Utility;
namespace ModernKeePassLib.Native namespace ModernKeePassLib.Native
{ {
internal static class NativeMethods internal static partial class NativeMethods
{ {
internal const int MAX_PATH = 260; internal const int MAX_PATH = 260;
// internal const uint TF_SFT_SHOWNORMAL = 0x00000001;
// internal const uint TF_SFT_HIDDEN = 0x00000008;
/* [DllImport("KeePassNtv32.dll", EntryPoint = "TransformKey")] /* [DllImport("KeePassNtv32.dll", EntryPoint = "TransformKey")]
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
private static extern bool TransformKey32(IntPtr pBuf256, private static extern bool TransformKey32(IntPtr pBuf256,
@@ -65,7 +72,7 @@ namespace ModernKeePassLib.Native
else else
return TransformKeyTimed32(pBuf256, pKey256, ref puRounds, uSeconds); return TransformKeyTimed32(pBuf256, pKey256, ref puRounds, uSeconds);
} */ } */
/*
[DllImport("KeePassLibC32.dll", EntryPoint = "TransformKey256")] [DllImport("KeePassLibC32.dll", EntryPoint = "TransformKey256")]
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
private static extern bool TransformKey32(IntPtr pBuf256, private static extern bool TransformKey32(IntPtr pBuf256,
@@ -95,11 +102,25 @@ namespace ModernKeePassLib.Native
{ {
if(Marshal.SizeOf(typeof(IntPtr)) == 8) if(Marshal.SizeOf(typeof(IntPtr)) == 8)
return TransformKeyBenchmark64(uTimeMs); return TransformKeyBenchmark64(uTimeMs);
else return TransformKeyBenchmark32(uTimeMs);
return TransformKeyBenchmark32(uTimeMs);
} }
*/
#if !KeePassLibSD && TODO /* [DllImport("KeePassLibC32.dll", EntryPoint = "TF_ShowLangBar")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool TF_ShowLangBar32(UInt32 dwFlags);
[DllImport("KeePassLibC64.dll", EntryPoint = "TF_ShowLangBar")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool TF_ShowLangBar64(UInt32 dwFlags);
internal static bool TfShowLangBar(uint dwFlags)
{
if(Marshal.SizeOf(typeof(IntPtr)) == 8)
return TF_ShowLangBar64(dwFlags);
return TF_ShowLangBar32(dwFlags);
} */
#if (!KeePassLibSD && !KeePassRT)
[DllImport("ShlWApi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)] [DllImport("ShlWApi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static extern int StrCmpLogicalW(string x, string y); internal static extern int StrCmpLogicalW(string x, string y);
@@ -114,7 +135,7 @@ namespace ModernKeePassLib.Native
private static void TestNaturalComparisonsSupport() private static void TestNaturalComparisonsSupport()
{ {
#if KeePassLibSD || !TODO #if (KeePassLibSD || KeePassRT)
#warning No native natural comparisons supported. #warning No native natural comparisons supported.
m_bSupportsLogicalCmp = false; m_bSupportsLogicalCmp = false;
#else #else
@@ -143,11 +164,36 @@ namespace ModernKeePassLib.Native
if(m_bSupportsLogicalCmp.HasValue == false) TestNaturalComparisonsSupport(); if(m_bSupportsLogicalCmp.HasValue == false) TestNaturalComparisonsSupport();
if(m_bSupportsLogicalCmp.Value == false) return 0; if(m_bSupportsLogicalCmp.Value == false) return 0;
#if KeePassLibSD || !TODO #if (KeePassLibSD || KeePassRT)
#warning No native natural comparisons supported. #warning No native natural comparisons supported.
return x.CompareTo(y); return x.CompareTo(y);
#else #else
return StrCmpLogicalW(x, y); return StrCmpLogicalW(x, y);
#endif
}
internal static string GetUserRuntimeDir()
{
#if !KeePassLibSD
#if KeePassRT
string strRtDir = Windows.Storage.ApplicationData.Current.LocalFolder.Path;
#else
string strRtDir = Environment.GetEnvironmentVariable("XDG_RUNTIME_DIR");
if(string.IsNullOrEmpty(strRtDir))
strRtDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
if(string.IsNullOrEmpty(strRtDir))
{
Debug.Assert(false);
return Path.GetTempPath(); // Not UrlUtil (otherwise cyclic)
}
#endif
strRtDir = UrlUtil.EnsureTerminatingSeparator(strRtDir, false);
strRtDir += PwDefs.ShortProductName;
return strRtDir;
#else
return Path.GetTempPath();
#endif #endif
} }
} }

View File

@@ -39,5 +39,5 @@ using System.Runtime.InteropServices;
//[assembly: Guid("395f6eec-a1e0-4438-aa82-b75099348134")] //[assembly: Guid("395f6eec-a1e0-4438-aa82-b75099348134")]
// Assembly version information // Assembly version information
[assembly: AssemblyVersion("2.19.0.*")] [assembly: AssemblyVersion("2.36.0.*")]
[assembly: AssemblyFileVersion("2.19.0.0")] [assembly: AssemblyFileVersion("2.36.0.0")]

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -18,20 +18,18 @@
*/ */
using System; using System;
//using System.Drawing; using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Imaging;
// Bert TODO: http://blog.tallcomponents.com/2012/06/windows-8-release-preview-back-to-earth.html
namespace ModernKeePassLib namespace ModernKeePassLib
{ {
/// <summary> /// <summary>
/// Custom icon. <c>PwCustomIcon</c> objects are immutable. /// Custom icon. <c>PwCustomIcon</c> objects are immutable.
/// </summary> /// </summary>
public sealed class PwCustomIcon public sealed class PwCustomIcon
{ {
private PwUuid m_pwUuid; private PwUuid m_pwUuid;
private byte[] m_pbImageDataPng; private byte[] m_pbImageDataPng;
private BitmapImage m_pCachedImage; private Image m_pCachedImage;
public PwUuid Uuid public PwUuid Uuid
{ {
@@ -43,7 +41,7 @@ namespace ModernKeePassLib
get { return m_pbImageDataPng; } get { return m_pbImageDataPng; }
} }
public BitmapImage Image public Image Image
{ {
get { return m_pCachedImage; } get { return m_pCachedImage; }
} }
@@ -52,8 +50,8 @@ namespace ModernKeePassLib
{ {
Debug.Assert(pwUuid != null); Debug.Assert(pwUuid != null);
if(pwUuid == null) throw new ArgumentNullException("pwUuid"); if(pwUuid == null) throw new ArgumentNullException("pwUuid");
Debug.Assert(pwUuid != PwUuid.Zero); Debug.Assert(!pwUuid.Equals(PwUuid.Zero));
if(pwUuid == PwUuid.Zero) throw new ArgumentException("pwUuid == 0"); if(pwUuid.Equals(PwUuid.Zero)) throw new ArgumentException("pwUuid == 0");
Debug.Assert(pbImageDataPng != null); Debug.Assert(pbImageDataPng != null);
if(pbImageDataPng == null) throw new ArgumentNullException("pbImageDataPng"); if(pbImageDataPng == null) throw new ArgumentNullException("pbImageDataPng");
@@ -61,10 +59,11 @@ namespace ModernKeePassLib
m_pwUuid = pwUuid; m_pwUuid = pwUuid;
m_pbImageDataPng = pbImageDataPng; m_pbImageDataPng = pbImageDataPng;
#if !KeePassLibSD && false #if !KeePassLibSD
MemoryStream ms = new MemoryStream(m_pbImageDataPng, false); // MemoryStream ms = new MemoryStream(m_pbImageDataPng, false);
m_pCachedImage = Image.FromStream(ms); // m_pCachedImage = Image.FromStream(ms);
ms.Close(); // ms.Close();
//m_pCachedImage = GfxUtil.LoadImage(m_pbImageDataPng);
#else #else
m_pCachedImage = null; m_pCachedImage = null;
#endif #endif

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -19,27 +19,28 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Threading.Tasks; using Windows.UI;
using Windows.UI.Xaml.Media.Imaging; using Windows.UI.Xaml.Controls;
//using System.Drawing;
using ModernKeePassLib.WinRTAdaptors;
using ModernKeePassLib.Collections; using ModernKeePassLib.Collections;
using ModernKeePassLib.Cryptography;
using ModernKeePassLib.Cryptography.Cipher; using ModernKeePassLib.Cryptography.Cipher;
using ModernKeePassLib.Delegates; using ModernKeePassLib.Delegates;
using ModernKeePassLib.Interfaces; using ModernKeePassLib.Interfaces;
using ModernKeePassLib.Keys; using ModernKeePassLib.Keys;
using ModernKeePassLib.Resources;
using ModernKeePassLib.Security;
using ModernKeePassLib.Serialization; using ModernKeePassLib.Serialization;
using ModernKeePassLib.Utility; using ModernKeePassLib.Utility;
namespace ModernKeePassLib namespace ModernKeePassLib
{ {
/// <summary> /// <summary>
/// The core password manager class. It contains a number of groups, which /// The core password manager class. It contains a number of groups, which
/// contain the actual entries. /// contain the actual entries.
/// </summary> /// </summary>
public sealed class PwDatabase public sealed class PwDatabase
{ {
internal const int DefaultHistoryMaxItems = 10; // -1 = unlimited internal const int DefaultHistoryMaxItems = 10; // -1 = unlimited
internal const long DefaultHistoryMaxSize = 6 * 1024 * 1024; // -1 = unlimited internal const long DefaultHistoryMaxSize = 6 * 1024 * 1024; // -1 = unlimited
@@ -67,7 +68,7 @@ namespace ModernKeePassLib
private string m_strDefaultUserName = string.Empty; private string m_strDefaultUserName = string.Empty;
private DateTime m_dtDefaultUserChanged = PwDefs.DtDefaultNow; private DateTime m_dtDefaultUserChanged = PwDefs.DtDefaultNow;
private uint m_uMntncHistoryDays = 365; private uint m_uMntncHistoryDays = 365;
private Color m_clr = Color.Empty; private Color m_clr;
private DateTime m_dtKeyLastChanged = PwDefs.DtDefaultNow; private DateTime m_dtKeyLastChanged = PwDefs.DtDefaultNow;
private long m_lKeyChangeRecDays = -1; private long m_lKeyChangeRecDays = -1;
@@ -497,7 +498,7 @@ namespace ModernKeePassLib
m_strDefaultUserName = string.Empty; m_strDefaultUserName = string.Empty;
m_dtDefaultUserChanged = dtNow; m_dtDefaultUserChanged = dtNow;
m_uMntncHistoryDays = 365; m_uMntncHistoryDays = 365;
m_clr = Color.Empty; m_clr = new Color();
m_dtKeyLastChanged = dtNow; m_dtKeyLastChanged = dtNow;
m_lKeyChangeRecDays = -1; m_lKeyChangeRecDays = -1;
@@ -561,10 +562,9 @@ namespace ModernKeePassLib
/// <param name="ioSource">IO connection to load the database from.</param> /// <param name="ioSource">IO connection to load the database from.</param>
/// <param name="pwKey">Key used to open the specified database.</param> /// <param name="pwKey">Key used to open the specified database.</param>
/// <param name="slLogger">Logger, which gets all status messages.</param> /// <param name="slLogger">Logger, which gets all status messages.</param>
public async Task Open(IOConnectionInfo ioSource, CompositeKey pwKey, public void Open(IOConnectionInfo ioSource, CompositeKey pwKey,
IStatusLogger slLogger) IStatusLogger slLogger)
{ {
Debug.Assert(ioSource != null); Debug.Assert(ioSource != null);
if(ioSource == null) throw new ArgumentNullException("ioSource"); if(ioSource == null) throw new ArgumentNullException("ioSource");
Debug.Assert(pwKey != null); Debug.Assert(pwKey != null);
@@ -582,17 +582,15 @@ namespace ModernKeePassLib
m_bModified = false; m_bModified = false;
Kdb4File kdb4 = new Kdb4File(this); KdbxFile kdbx = new KdbxFile(this);
kdb4.DetachBinaries = m_strDetachBins; kdbx.DetachBinaries = m_strDetachBins;
IOConnection ioc = new IOConnection(); Stream s = IOConnection.OpenRead(ioSource);
Stream s = await ioc.OpenRead(ioSource); kdbx.Load(s, KdbxFormat.Default, slLogger);
kdb4.Load(s, Kdb4Format.Default, slLogger); s.Dispose();
s.Dispose(); m_pbHashOfLastIO = kdbx.HashOfFileOnDisk;
m_pbHashOfFileOnDisk = kdbx.HashOfFileOnDisk;
m_pbHashOfLastIO = kdb4.HashOfFileOnDisk;
m_pbHashOfFileOnDisk = kdb4.HashOfFileOnDisk;
Debug.Assert(m_pbHashOfFileOnDisk != null); Debug.Assert(m_pbHashOfFileOnDisk != null);
m_bDatabaseOpened = true; m_bDatabaseOpened = true;
@@ -610,7 +608,7 @@ namespace ModernKeePassLib
/// it has been opened from. /// it has been opened from.
/// </summary> /// </summary>
/// <param name="slLogger">Logger that recieves status information.</param> /// <param name="slLogger">Logger that recieves status information.</param>
public async void Save(IStatusLogger slLogger) public void Save(IStatusLogger slLogger)
{ {
Debug.Assert(ValidateUuidUniqueness()); Debug.Assert(ValidateUuidUniqueness());
@@ -620,10 +618,10 @@ namespace ModernKeePassLib
{ {
FileTransactionEx ft = new FileTransactionEx(m_ioSource, FileTransactionEx ft = new FileTransactionEx(m_ioSource,
m_bUseFileTransactions); m_bUseFileTransactions);
Stream s = await ft.OpenWrite(); Stream s = ft.OpenWrite();
Kdb4File kdb = new Kdb4File(this); KdbxFile kdb = new KdbxFile(this);
kdb.Save(s, null, Kdb4Format.Default, slLogger); kdb.Save(s, null, KdbxFormat.Default, slLogger);
ft.CommitWrite(); ft.CommitWrite();
@@ -631,8 +629,6 @@ namespace ModernKeePassLib
m_pbHashOfFileOnDisk = kdb.HashOfFileOnDisk; m_pbHashOfFileOnDisk = kdb.HashOfFileOnDisk;
Debug.Assert(m_pbHashOfFileOnDisk != null); Debug.Assert(m_pbHashOfFileOnDisk != null);
} }
catch (Exception ex)
{ }
finally { if(fl != null) fl.Dispose(); } finally { if(fl != null) fl.Dispose(); }
m_bModified = false; m_bModified = false;
@@ -688,15 +684,15 @@ namespace ModernKeePassLib
Clear(); Clear();
} }
public void MergeIn(PwDatabase pwSource, PwMergeMethod mm) public void MergeIn(PwDatabase pdSource, PwMergeMethod mm)
{ {
MergeIn(pwSource, mm, null); MergeIn(pdSource, mm, null);
} }
/// <summary> /// <summary>
/// Synchronize the current database with another one. /// Synchronize the current database with another one.
/// </summary> /// </summary>
/// <param name="pwSource">Input database to synchronize with. This input /// <param name="pdSource">Input database to synchronize with. This input
/// database is used to update the current one, but is not modified! You /// database is used to update the current one, but is not modified! You
/// must copy the current object if you want a second instance of the /// must copy the current object if you want a second instance of the
/// synchronized database. The input database must not be seen as valid /// synchronized database. The input database must not be seen as valid
@@ -704,27 +700,38 @@ namespace ModernKeePassLib
/// <param name="mm">Merge method.</param> /// <param name="mm">Merge method.</param>
/// <param name="slStatus">Logger to report status messages to. /// <param name="slStatus">Logger to report status messages to.
/// May be <c>null</c>.</param> /// May be <c>null</c>.</param>
public void MergeIn(PwDatabase pwSource, PwMergeMethod mm, public void MergeIn(PwDatabase pdSource, PwMergeMethod mm,
IStatusLogger slStatus) IStatusLogger slStatus)
{ {
if(pwSource == null) throw new ArgumentNullException("pwSource"); if(pdSource == null) throw new ArgumentNullException("pdSource");
PwGroup pgOrgStructure = m_pgRootGroup.CloneStructure(); PwGroup pgOrgStructure = m_pgRootGroup.CloneStructure();
PwGroup pgSrcStructure = pwSource.m_pgRootGroup.CloneStructure(); PwGroup pgSrcStructure = pdSource.m_pgRootGroup.CloneStructure();
if(mm == PwMergeMethod.CreateNewUuids) if(mm == PwMergeMethod.CreateNewUuids)
pwSource.RootGroup.CreateNewItemUuids(true, true, true); {
pdSource.RootGroup.CreateNewItemUuids(true, true, true);
pdSource.RootGroup.Uuid = new PwUuid(true);
}
GroupHandler gh = delegate(PwGroup pg) GroupHandler gh = delegate(PwGroup pg)
{ {
if(pg == pwSource.m_pgRootGroup) return true; // if(pg == pdSource.m_pgRootGroup) return true;
PwGroup pgLocal = m_pgRootGroup.FindGroup(pg.Uuid, true); PwGroup pgLocal = m_pgRootGroup.FindGroup(pg.Uuid, true);
if(pgLocal == null) if(pgLocal == null)
{ {
PwGroup pgSourceParent = pg.ParentGroup; PwGroup pgSourceParent = pg.ParentGroup;
PwGroup pgLocalContainer; PwGroup pgLocalContainer;
if(pgSourceParent == pwSource.m_pgRootGroup) if(pgSourceParent == null)
{
// pg is the root group of pdSource, and no corresponding
// local group was found; create the group within the
// local root group
Debug.Assert(pg == pdSource.m_pgRootGroup);
pgLocalContainer = m_pgRootGroup;
}
else if(pgSourceParent == pdSource.m_pgRootGroup)
pgLocalContainer = m_pgRootGroup; pgLocalContainer = m_pgRootGroup;
else else
pgLocalContainer = m_pgRootGroup.FindGroup(pgSourceParent.Uuid, true); pgLocalContainer = m_pgRootGroup.FindGroup(pgSourceParent.Uuid, true);
@@ -760,7 +767,7 @@ namespace ModernKeePassLib
{ {
PwGroup pgSourceParent = pe.ParentGroup; PwGroup pgSourceParent = pe.ParentGroup;
PwGroup pgLocalContainer; PwGroup pgLocalContainer;
if(pgSourceParent == pwSource.m_pgRootGroup) if(pgSourceParent == pdSource.m_pgRootGroup)
pgLocalContainer = m_pgRootGroup; pgLocalContainer = m_pgRootGroup;
else else
pgLocalContainer = m_pgRootGroup.FindGroup(pgSourceParent.Uuid, true); pgLocalContainer = m_pgRootGroup.FindGroup(pgSourceParent.Uuid, true);
@@ -783,12 +790,12 @@ namespace ModernKeePassLib
bool bOrgBackup = !bEquals; bool bOrgBackup = !bEquals;
if(mm != PwMergeMethod.OverwriteExisting) if(mm != PwMergeMethod.OverwriteExisting)
bOrgBackup &= (pe.LastModificationTime > peLocal.LastModificationTime); bOrgBackup &= (TimeUtil.CompareLastMod(pe, peLocal, true) > 0);
bOrgBackup &= !pe.HasBackupOfData(peLocal, false, true); bOrgBackup &= !pe.HasBackupOfData(peLocal, false, true);
if(bOrgBackup) peLocal.CreateBackup(null); // Maintain at end if(bOrgBackup) peLocal.CreateBackup(null); // Maintain at end
bool bSrcBackup = !bEquals && (mm != PwMergeMethod.OverwriteExisting); bool bSrcBackup = !bEquals && (mm != PwMergeMethod.OverwriteExisting);
bSrcBackup &= (peLocal.LastModificationTime > pe.LastModificationTime); bSrcBackup &= (TimeUtil.CompareLastMod(peLocal, pe, true) > 0);
bSrcBackup &= !peLocal.HasBackupOfData(pe, false, true); bSrcBackup &= !peLocal.HasBackupOfData(pe, false, true);
if(bSrcBackup) pe.CreateBackup(null); // Maintain at end if(bSrcBackup) pe.CreateBackup(null); // Maintain at end
@@ -807,7 +814,8 @@ namespace ModernKeePassLib
return ((slStatus != null) ? slStatus.ContinueWork() : true); return ((slStatus != null) ? slStatus.ContinueWork() : true);
}; };
if(!pwSource.RootGroup.TraverseTree(TraversalMethod.PreOrder, gh, eh)) gh(pdSource.RootGroup);
if(!pdSource.RootGroup.TraverseTree(TraversalMethod.PreOrder, gh, eh))
throw new InvalidOperationException(); throw new InvalidOperationException();
IStatusLogger slPrevStatus = m_slStatus; IStatusLogger slPrevStatus = m_slStatus;
@@ -815,7 +823,7 @@ namespace ModernKeePassLib
if(mm == PwMergeMethod.Synchronize) if(mm == PwMergeMethod.Synchronize)
{ {
ApplyDeletions(pwSource.m_vDeletedObjects, true); ApplyDeletions(pdSource.m_vDeletedObjects, true);
ApplyDeletions(m_vDeletedObjects, false); ApplyDeletions(m_vDeletedObjects, false);
PwObjectPool ppOrgGroups = PwObjectPool.FromGroupRecursive( PwObjectPool ppOrgGroups = PwObjectPool.FromGroupRecursive(
@@ -836,18 +844,18 @@ namespace ModernKeePassLib
// Must be called *after* merging groups, because group UUIDs // Must be called *after* merging groups, because group UUIDs
// are required for recycle bin and entry template UUIDs // are required for recycle bin and entry template UUIDs
MergeInDbProperties(pwSource, mm); MergeInDbProperties(pdSource, mm);
MergeInCustomIcons(pwSource); MergeInCustomIcons(pdSource);
MaintainBackups(); MaintainBackups();
m_slStatus = slPrevStatus; m_slStatus = slPrevStatus;
} }
private void MergeInCustomIcons(PwDatabase pwSource) private void MergeInCustomIcons(PwDatabase pdSource)
{ {
foreach(PwCustomIcon pwci in pwSource.CustomIcons) foreach(PwCustomIcon pwci in pdSource.CustomIcons)
{ {
if(GetCustomIconIndex(pwci.Uuid) >= 0) continue; if(GetCustomIconIndex(pwci.Uuid) >= 0) continue;
@@ -856,10 +864,6 @@ namespace ModernKeePassLib
} }
} }
/// <summary>
/// Apply a list of deleted objects.
/// </summary>
/// <param name="listDelObjects">List of deleted objects.</param>
private void ApplyDeletions(PwObjectList<PwDeletedObject> listDelObjects, private void ApplyDeletions(PwObjectList<PwDeletedObject> listDelObjects,
bool bCopyDeletionInfoToLocal) bool bCopyDeletionInfoToLocal)
{ {
@@ -874,9 +878,12 @@ namespace ModernKeePassLib
foreach(PwDeletedObject pdo in listDelObjects) foreach(PwDeletedObject pdo in listDelObjects)
{ {
if(pg.Uuid.EqualsValue(pdo.Uuid)) if(pg.Uuid.Equals(pdo.Uuid))
if(pg.LastModificationTime < pdo.DeletionTime) {
if(TimeUtil.Compare(pg.LastModificationTime,
pdo.DeletionTime, true) < 0)
listGroupsToDelete.AddLast(pg); listGroupsToDelete.AddLast(pg);
}
} }
return ((m_slStatus != null) ? m_slStatus.ContinueWork() : true); return ((m_slStatus != null) ? m_slStatus.ContinueWork() : true);
@@ -886,9 +893,12 @@ namespace ModernKeePassLib
{ {
foreach(PwDeletedObject pdo in listDelObjects) foreach(PwDeletedObject pdo in listDelObjects)
{ {
if(pe.Uuid.EqualsValue(pdo.Uuid)) if(pe.Uuid.Equals(pdo.Uuid))
if(pe.LastModificationTime < pdo.DeletionTime) {
if(TimeUtil.Compare(pe.LastModificationTime,
pdo.DeletionTime, true) < 0)
listEntriesToDelete.AddLast(pe); listEntriesToDelete.AddLast(pe);
}
} }
return ((m_slStatus != null) ? m_slStatus.ContinueWork() : true); return ((m_slStatus != null) ? m_slStatus.ContinueWork() : true);
@@ -909,7 +919,7 @@ namespace ModernKeePassLib
foreach(PwDeletedObject pdoLocal in m_vDeletedObjects) foreach(PwDeletedObject pdoLocal in m_vDeletedObjects)
{ {
if(pdoNew.Uuid.EqualsValue(pdoLocal.Uuid)) if(pdoNew.Uuid.Equals(pdoLocal.Uuid))
{ {
bCopy = false; bCopy = false;
@@ -942,8 +952,15 @@ namespace ModernKeePassLib
if(ptSrc == null) continue; if(ptSrc == null) continue;
PwGroup pgOrgParent = ptOrg.ParentGroup; PwGroup pgOrgParent = ptOrg.ParentGroup;
// vGroups does not contain the root group, thus pgOrgParent
// should not be null
if(pgOrgParent == null) { Debug.Assert(false); continue; }
PwGroup pgSrcParent = ptSrc.ParentGroup; PwGroup pgSrcParent = ptSrc.ParentGroup;
if(pgOrgParent.Uuid.EqualsValue(pgSrcParent.Uuid)) // pgSrcParent may be null (for the source root group)
if(pgSrcParent == null) continue;
if(pgOrgParent.Uuid.Equals(pgSrcParent.Uuid))
{ {
pg.LocationChanged = ((ptSrc.LocationChanged > ptOrg.LocationChanged) ? pg.LocationChanged = ((ptSrc.LocationChanged > ptOrg.LocationChanged) ?
ptSrc.LocationChanged : ptOrg.LocationChanged); ptSrc.LocationChanged : ptOrg.LocationChanged);
@@ -963,7 +980,7 @@ namespace ModernKeePassLib
} }
else else
{ {
Debug.Assert(pg.ParentGroup.Uuid.EqualsValue(pgOrgParent.Uuid)); Debug.Assert(pg.ParentGroup.Uuid.Equals(pgOrgParent.Uuid));
Debug.Assert(pg.LocationChanged == ptOrg.LocationChanged); Debug.Assert(pg.LocationChanged == ptOrg.LocationChanged);
} }
} }
@@ -989,7 +1006,7 @@ namespace ModernKeePassLib
PwGroup pgOrg = ptOrg.ParentGroup; PwGroup pgOrg = ptOrg.ParentGroup;
PwGroup pgSrc = ptSrc.ParentGroup; PwGroup pgSrc = ptSrc.ParentGroup;
if(pgOrg.Uuid.EqualsValue(pgSrc.Uuid)) if(pgOrg.Uuid.Equals(pgSrc.Uuid))
{ {
pe.LocationChanged = ((ptSrc.LocationChanged > ptOrg.LocationChanged) ? pe.LocationChanged = ((ptSrc.LocationChanged > ptOrg.LocationChanged) ?
ptSrc.LocationChanged : ptOrg.LocationChanged); ptSrc.LocationChanged : ptOrg.LocationChanged);
@@ -1007,7 +1024,7 @@ namespace ModernKeePassLib
} }
else else
{ {
Debug.Assert(pe.ParentGroup.Uuid.EqualsValue(pgOrg.Uuid)); Debug.Assert(pe.ParentGroup.Uuid.Equals(pgOrg.Uuid));
Debug.Assert(pe.LocationChanged == ptOrg.LocationChanged); Debug.Assert(pe.LocationChanged == ptOrg.LocationChanged);
} }
} }
@@ -1084,7 +1101,7 @@ namespace ModernKeePassLib
bool bAdded = false; bool bAdded = false;
foreach(PwUuid puBefore in qRelBefore) foreach(PwUuid puBefore in qRelBefore)
{ {
if(puBefore.EqualsValue(pt.Uuid)) if(puBefore.Equals(pt.Uuid))
{ {
qBefore.Enqueue(pt); qBefore.Enqueue(pt);
bAdded = true; bAdded = true;
@@ -1095,7 +1112,7 @@ namespace ModernKeePassLib
foreach(PwUuid puAfter in qRelAfter) foreach(PwUuid puAfter in qRelAfter)
{ {
if(puAfter.EqualsValue(pt.Uuid)) if(puAfter.Equals(pt.Uuid))
{ {
qAfter.Enqueue(pt); qAfter.Enqueue(pt);
bAdded = true; bAdded = true;
@@ -1159,7 +1176,16 @@ namespace ModernKeePassLib
{ {
uPosMax = u; uPosMax = u;
dtMax = ptOrg.LocationChanged; // No 'continue' dtMax = ptOrg.LocationChanged; // No 'continue'
vNeighborSrc = ptOrg.ParentGroup.GetObjects(false, bEntries);
PwGroup pgParent = ptOrg.ParentGroup;
if(pgParent != null)
vNeighborSrc = pgParent.GetObjects(false, bEntries);
else
{
Debug.Assert(false); // Org root should be excluded
vNeighborSrc = new List<IStructureItem>();
vNeighborSrc.Add(ptOrg);
}
} }
// IStructureItem ptSrc = pgSrcStructure.FindObject(pt.Uuid, true, bEntries); // IStructureItem ptSrc = pgSrcStructure.FindObject(pt.Uuid, true, bEntries);
@@ -1168,7 +1194,16 @@ namespace ModernKeePassLib
{ {
uPosMax = u; uPosMax = u;
dtMax = ptSrc.LocationChanged; // No 'continue' dtMax = ptSrc.LocationChanged; // No 'continue'
vNeighborSrc = ptSrc.ParentGroup.GetObjects(false, bEntries);
PwGroup pgParent = ptSrc.ParentGroup;
if(pgParent != null)
vNeighborSrc = pgParent.GetObjects(false, bEntries);
else
{
// pgParent may be null (for the source root group)
vNeighborSrc = new List<IStructureItem>();
vNeighborSrc.Add(ptSrc);
}
} }
} }
@@ -1190,7 +1225,7 @@ namespace ModernKeePassLib
{ {
PwUuid pw = vItems[i].Uuid; PwUuid pw = vItems[i].Uuid;
if(pw.EqualsValue(pwPivot)) bBefore = false; if(pw.Equals(pwPivot)) bBefore = false;
else if(bBefore) qBefore.Enqueue(pw); else if(bBefore) qBefore.Enqueue(pw);
else qAfter.Enqueue(pw); else qAfter.Enqueue(pw);
} }
@@ -1226,8 +1261,8 @@ namespace ModernKeePassLib
PwGroup pgSrcParent = ptSrc.ParentGroup; PwGroup pgSrcParent = ptSrc.ParentGroup;
if(pgSrcParent == null) return true; // Root might be in tree if(pgSrcParent == null) return true; // Root might be in tree
if(!ptFirst.ParentGroup.Uuid.EqualsValue(pgOrgParent.Uuid)) return true; if(!ptFirst.ParentGroup.Uuid.Equals(pgOrgParent.Uuid)) return true;
if(!pgOrgParent.Uuid.EqualsValue(pgSrcParent.Uuid)) return true; if(!pgOrgParent.Uuid.Equals(pgSrcParent.Uuid)) return true;
List<IStructureItem> lOrg = pgOrgParent.GetObjects(false, bEntries); List<IStructureItem> lOrg = pgOrgParent.GetObjects(false, bEntries);
List<IStructureItem> lSrc = pgSrcParent.GetObjects(false, bEntries); List<IStructureItem> lSrc = pgSrcParent.GetObjects(false, bEntries);
@@ -1239,8 +1274,8 @@ namespace ModernKeePassLib
IStructureItem pt = vItems.GetAt(u); IStructureItem pt = vItems.GetAt(u);
Debug.Assert(pt.ParentGroup == ptFirst.ParentGroup); Debug.Assert(pt.ParentGroup == ptFirst.ParentGroup);
if(!pt.Uuid.EqualsValue(lOrg[(int)u].Uuid)) return true; if(!pt.Uuid.Equals(lOrg[(int)u].Uuid)) return true;
if(!pt.Uuid.EqualsValue(lSrc[(int)u].Uuid)) return true; if(!pt.Uuid.Equals(lSrc[(int)u].Uuid)) return true;
if(pt.LocationChanged != lOrg[(int)u].LocationChanged) return true; if(pt.LocationChanged != lOrg[(int)u].LocationChanged) return true;
if(pt.LocationChanged != lSrc[(int)u].LocationChanged) return true; if(pt.LocationChanged != lSrc[(int)u].LocationChanged) return true;
} }
@@ -1248,41 +1283,41 @@ namespace ModernKeePassLib
return false; return false;
} }
private void MergeInDbProperties(PwDatabase pwSource, PwMergeMethod mm) private void MergeInDbProperties(PwDatabase pdSource, PwMergeMethod mm)
{ {
if(pwSource == null) { Debug.Assert(false); return; } if(pdSource == null) { Debug.Assert(false); return; }
if((mm == PwMergeMethod.KeepExisting) || (mm == PwMergeMethod.None)) if((mm == PwMergeMethod.KeepExisting) || (mm == PwMergeMethod.None))
return; return;
bool bForce = (mm == PwMergeMethod.OverwriteExisting); bool bForce = (mm == PwMergeMethod.OverwriteExisting);
if(bForce || (pwSource.m_dtNameChanged > m_dtNameChanged)) if(bForce || (pdSource.m_dtNameChanged > m_dtNameChanged))
{ {
m_strName = pwSource.m_strName; m_strName = pdSource.m_strName;
m_dtNameChanged = pwSource.m_dtNameChanged; m_dtNameChanged = pdSource.m_dtNameChanged;
} }
if(bForce || (pwSource.m_dtDescChanged > m_dtDescChanged)) if(bForce || (pdSource.m_dtDescChanged > m_dtDescChanged))
{ {
m_strDesc = pwSource.m_strDesc; m_strDesc = pdSource.m_strDesc;
m_dtDescChanged = pwSource.m_dtDescChanged; m_dtDescChanged = pdSource.m_dtDescChanged;
} }
if(bForce || (pwSource.m_dtDefaultUserChanged > m_dtDefaultUserChanged)) if(bForce || (pdSource.m_dtDefaultUserChanged > m_dtDefaultUserChanged))
{ {
m_strDefaultUserName = pwSource.m_strDefaultUserName; m_strDefaultUserName = pdSource.m_strDefaultUserName;
m_dtDefaultUserChanged = pwSource.m_dtDefaultUserChanged; m_dtDefaultUserChanged = pdSource.m_dtDefaultUserChanged;
} }
if(bForce) m_clr = pwSource.m_clr; if(bForce) m_clr = pdSource.m_clr;
PwUuid pwPrefBin = m_pwRecycleBin, pwAltBin = pwSource.m_pwRecycleBin; PwUuid pwPrefBin = m_pwRecycleBin, pwAltBin = pdSource.m_pwRecycleBin;
if(bForce || (pwSource.m_dtRecycleBinChanged > m_dtRecycleBinChanged)) if(bForce || (pdSource.m_dtRecycleBinChanged > m_dtRecycleBinChanged))
{ {
pwPrefBin = pwSource.m_pwRecycleBin; pwPrefBin = pdSource.m_pwRecycleBin;
pwAltBin = m_pwRecycleBin; pwAltBin = m_pwRecycleBin;
m_bUseRecycleBin = pwSource.m_bUseRecycleBin; m_bUseRecycleBin = pdSource.m_bUseRecycleBin;
m_dtRecycleBinChanged = pwSource.m_dtRecycleBinChanged; m_dtRecycleBinChanged = pdSource.m_dtRecycleBinChanged;
} }
if(m_pgRootGroup.FindGroup(pwPrefBin, true) != null) if(m_pgRootGroup.FindGroup(pwPrefBin, true) != null)
m_pwRecycleBin = pwPrefBin; m_pwRecycleBin = pwPrefBin;
@@ -1290,12 +1325,12 @@ namespace ModernKeePassLib
m_pwRecycleBin = pwAltBin; m_pwRecycleBin = pwAltBin;
else m_pwRecycleBin = PwUuid.Zero; // Debug.Assert(false); else m_pwRecycleBin = PwUuid.Zero; // Debug.Assert(false);
PwUuid pwPrefTmp = m_pwEntryTemplatesGroup, pwAltTmp = pwSource.m_pwEntryTemplatesGroup; PwUuid pwPrefTmp = m_pwEntryTemplatesGroup, pwAltTmp = pdSource.m_pwEntryTemplatesGroup;
if(bForce || (pwSource.m_dtEntryTemplatesChanged > m_dtEntryTemplatesChanged)) if(bForce || (pdSource.m_dtEntryTemplatesChanged > m_dtEntryTemplatesChanged))
{ {
pwPrefTmp = pwSource.m_pwEntryTemplatesGroup; pwPrefTmp = pdSource.m_pwEntryTemplatesGroup;
pwAltTmp = m_pwEntryTemplatesGroup; pwAltTmp = m_pwEntryTemplatesGroup;
m_dtEntryTemplatesChanged = pwSource.m_dtEntryTemplatesChanged; m_dtEntryTemplatesChanged = pdSource.m_dtEntryTemplatesChanged;
} }
if(m_pgRootGroup.FindGroup(pwPrefTmp, true) != null) if(m_pgRootGroup.FindGroup(pwPrefTmp, true) != null)
m_pwEntryTemplatesGroup = pwPrefTmp; m_pwEntryTemplatesGroup = pwPrefTmp;
@@ -1307,10 +1342,7 @@ namespace ModernKeePassLib
private void MergeEntryHistory(PwEntry pe, PwEntry peSource, private void MergeEntryHistory(PwEntry pe, PwEntry peSource,
PwMergeMethod mm) PwMergeMethod mm)
{ {
Debug.Assert(false, "not yet implemented"); if(!pe.Uuid.Equals(peSource.Uuid)) { Debug.Assert(false); return; }
return ;
#if TODO
if(!pe.Uuid.EqualsValue(peSource.Uuid)) { Debug.Assert(false); return; }
if(pe.History.UCount == peSource.History.UCount) if(pe.History.UCount == peSource.History.UCount)
{ {
@@ -1330,31 +1362,35 @@ namespace ModernKeePassLib
if((m_slStatus != null) && !m_slStatus.ContinueWork()) return; if((m_slStatus != null) && !m_slStatus.ContinueWork()) return;
SortedList<DateTime, PwEntry> list = new SortedList<DateTime, PwEntry>(); IDictionary<DateTime, PwEntry> dict =
#if KeePassLibSD
new SortedList<DateTime, PwEntry>();
#else
new SortedDictionary<DateTime, PwEntry>();
#endif
foreach(PwEntry peOrg in pe.History) foreach(PwEntry peOrg in pe.History)
{ {
list[peOrg.LastModificationTime] = peOrg; dict[peOrg.LastModificationTime] = peOrg;
} }
foreach(PwEntry peSrc in peSource.History) foreach(PwEntry peSrc in peSource.History)
{ {
DateTime dt = peSrc.LastModificationTime; DateTime dt = peSrc.LastModificationTime;
if(list.ContainsKey(dt)) if(dict.ContainsKey(dt))
{ {
if(mm == PwMergeMethod.OverwriteExisting) if(mm == PwMergeMethod.OverwriteExisting)
list[dt] = peSrc.CloneDeep(); dict[dt] = peSrc.CloneDeep();
} }
else list[dt] = peSrc.CloneDeep(); else dict[dt] = peSrc.CloneDeep();
} }
pe.History.Clear(); pe.History.Clear();
foreach(KeyValuePair<DateTime, PwEntry> kvpCur in list) foreach(KeyValuePair<DateTime, PwEntry> kvpCur in dict)
{ {
Debug.Assert(kvpCur.Value.Uuid.EqualsValue(pe.Uuid)); Debug.Assert(kvpCur.Value.Uuid.Equals(pe.Uuid));
Debug.Assert(kvpCur.Value.History.UCount == 0); Debug.Assert(kvpCur.Value.History.UCount == 0);
pe.History.Add(kvpCur.Value); pe.History.Add(kvpCur.Value);
} }
#endif
} }
public bool MaintainBackups() public bool MaintainBackups()
@@ -1378,12 +1414,12 @@ namespace ModernKeePassLib
/// <param name="strFile">Source file.</param> /// <param name="strFile">Source file.</param>
public void Synchronize(string strFile) public void Synchronize(string strFile)
{ {
PwDatabase pwSource = new PwDatabase(); PwDatabase pdSource = new PwDatabase();
IOConnectionInfo ioc = IOConnectionInfo.FromPath(strFile); IOConnectionInfo ioc = IOConnectionInfo.FromPath(strFile);
pwSource.Open(ioc, m_pwUserKey, null); pdSource.Open(ioc, m_pwUserKey, null);
MergeIn(pwSource, PwMergeMethod.Synchronize); MergeIn(pdSource, PwMergeMethod.Synchronize);
} */ } */
/// <summary> /// <summary>
@@ -1393,32 +1429,50 @@ namespace ModernKeePassLib
/// <returns>Index of the icon.</returns> /// <returns>Index of the icon.</returns>
public int GetCustomIconIndex(PwUuid pwIconId) public int GetCustomIconIndex(PwUuid pwIconId)
{ {
int nIndex = 0; for(int i = 0; i < m_vCustomIcons.Count; ++i)
foreach(PwCustomIcon pwci in m_vCustomIcons)
{ {
if(pwci.Uuid.EqualsValue(pwIconId)) PwCustomIcon pwci = m_vCustomIcons[i];
return nIndex; if(pwci.Uuid.Equals(pwIconId))
return i;
++nIndex;
} }
// Debug.Assert(false); // Do not assert // Debug.Assert(false); // Do not assert
return -1; return -1;
} }
public int GetCustomIconIndex(byte[] pbPngData)
{
if(pbPngData == null) { Debug.Assert(false); return -1; }
for(int i = 0; i < m_vCustomIcons.Count; ++i)
{
PwCustomIcon pwci = m_vCustomIcons[i];
byte[] pbEx = pwci.ImageDataPng;
if(pbEx == null) { Debug.Assert(false); continue; }
if(MemUtil.ArraysEqual(pbEx, pbPngData))
return i;
}
return -1;
}
/// <summary> /// <summary>
/// Get a custom icon. This function can return <c>null</c>, if /// Get a custom icon. This function can return <c>null</c>, if
/// no cached image of the icon is available. /// no cached image of the icon is available.
/// </summary> /// </summary>
/// <param name="pwIconId">ID of the icon.</param> /// <param name="pwIconId">ID of the icon.</param>
/// <returns>Image data.</returns> /// <returns>Image data.</returns>
public BitmapImage GetCustomIcon(PwUuid pwIconId) public Image GetCustomIcon(PwUuid pwIconId)
{ {
int nIndex = GetCustomIconIndex(pwIconId); #if PCL
return null;
#else
int nIndex = GetCustomIconIndex(pwIconId);
if(nIndex >= 0) return m_vCustomIcons[nIndex].Image; if(nIndex >= 0) return m_vCustomIcons[nIndex].Image;
else { Debug.Assert(false); return null; } else { Debug.Assert(false); return null; }
#endif
} }
public bool DeleteCustomIcons(List<PwUuid> vUuidsToDelete) public bool DeleteCustomIcons(List<PwUuid> vUuidsToDelete)
@@ -1430,11 +1484,11 @@ namespace ModernKeePassLib
GroupHandler gh = delegate(PwGroup pg) GroupHandler gh = delegate(PwGroup pg)
{ {
PwUuid uuidThis = pg.CustomIconUuid; PwUuid uuidThis = pg.CustomIconUuid;
if(uuidThis.EqualsValue(PwUuid.Zero)) return true; if(uuidThis.Equals(PwUuid.Zero)) return true;
foreach(PwUuid uuidDelete in vUuidsToDelete) foreach(PwUuid uuidDelete in vUuidsToDelete)
{ {
if(uuidThis.EqualsValue(uuidDelete)) if(uuidThis.Equals(uuidDelete))
{ {
pg.CustomIconUuid = PwUuid.Zero; pg.CustomIconUuid = PwUuid.Zero;
break; break;
@@ -1469,11 +1523,11 @@ namespace ModernKeePassLib
private static void RemoveCustomIconUuid(PwEntry pe, List<PwUuid> vToDelete) private static void RemoveCustomIconUuid(PwEntry pe, List<PwUuid> vToDelete)
{ {
PwUuid uuidThis = pe.CustomIconUuid; PwUuid uuidThis = pe.CustomIconUuid;
if(uuidThis.EqualsValue(PwUuid.Zero)) return; if(uuidThis.Equals(PwUuid.Zero)) return;
foreach(PwUuid uuidDelete in vToDelete) foreach(PwUuid uuidDelete in vToDelete)
{ {
if(uuidThis.EqualsValue(uuidDelete)) if(uuidThis.Equals(uuidDelete))
{ {
pe.CustomIconUuid = PwUuid.Zero; pe.CustomIconUuid = PwUuid.Zero;
break; break;
@@ -1493,7 +1547,7 @@ namespace ModernKeePassLib
GroupHandler gh = delegate(PwGroup pg) GroupHandler gh = delegate(PwGroup pg)
{ {
foreach(PwUuid u in l) foreach(PwUuid u in l)
bAllUnique &= !pg.Uuid.EqualsValue(u); bAllUnique &= !pg.Uuid.Equals(u);
l.Add(pg.Uuid); l.Add(pg.Uuid);
return bAllUnique; return bAllUnique;
}; };
@@ -1501,7 +1555,7 @@ namespace ModernKeePassLib
EntryHandler eh = delegate(PwEntry pe) EntryHandler eh = delegate(PwEntry pe)
{ {
foreach(PwUuid u in l) foreach(PwUuid u in l)
bAllUnique &= !pe.Uuid.EqualsValue(u); bAllUnique &= !pe.Uuid.Equals(u);
l.Add(pe.Uuid); l.Add(pe.Uuid);
return bAllUnique; return bAllUnique;
}; };
@@ -1599,7 +1653,7 @@ namespace ModernKeePassLib
PwEntry peB = l.GetAt(j); PwEntry peB = l.GetAt(j);
if(!DupEntriesEqual(peA, peB)) continue; if(!DupEntriesEqual(peA, peB)) continue;
bool bDeleteA = (peA.LastModificationTime <= peB.LastModificationTime); bool bDeleteA = (TimeUtil.CompareLastMod(peA, peB, true) <= 0);
if(pgRecycleBin != null) if(pgRecycleBin != null)
{ {
bool bAInBin = peA.IsContainedIn(pgRecycleBin); bool bAInBin = peA.IsContainedIn(pgRecycleBin);
@@ -1638,10 +1692,6 @@ namespace ModernKeePassLib
private static List<string> m_lStdFields = null; private static List<string> m_lStdFields = null;
private static bool DupEntriesEqual(PwEntry a, PwEntry b) private static bool DupEntriesEqual(PwEntry a, PwEntry b)
{ {
Debug.Assert(false, "not yet implemented");
return true;
#if TODO
if(m_lStdFields == null) m_lStdFields = PwDefs.GetStandardFields(); if(m_lStdFields == null) m_lStdFields = PwDefs.GetStandardFields();
foreach(string strStdKey in m_lStdFields) foreach(string strStdKey in m_lStdFields)
@@ -1689,7 +1739,6 @@ namespace ModernKeePassLib
} }
return true; return true;
#endif
} }
public uint DeleteEmptyGroups() public uint DeleteEmptyGroups()
@@ -1721,11 +1770,11 @@ namespace ModernKeePassLib
GroupHandler gh = delegate(PwGroup pg) GroupHandler gh = delegate(PwGroup pg)
{ {
PwUuid pwUuid = pg.CustomIconUuid; PwUuid pwUuid = pg.CustomIconUuid;
if((pwUuid == null) || pwUuid.EqualsValue(PwUuid.Zero)) return true; if((pwUuid == null) || pwUuid.Equals(PwUuid.Zero)) return true;
for(int i = 0; i < lToDelete.Count; ++i) for(int i = 0; i < lToDelete.Count; ++i)
{ {
if(lToDelete[i].EqualsValue(pwUuid)) if(lToDelete[i].Equals(pwUuid))
{ {
lToDelete.RemoveAt(i); lToDelete.RemoveAt(i);
break; break;
@@ -1738,11 +1787,11 @@ namespace ModernKeePassLib
EntryHandler eh = delegate(PwEntry pe) EntryHandler eh = delegate(PwEntry pe)
{ {
PwUuid pwUuid = pe.CustomIconUuid; PwUuid pwUuid = pe.CustomIconUuid;
if((pwUuid == null) || pwUuid.EqualsValue(PwUuid.Zero)) return true; if((pwUuid == null) || pwUuid.Equals(PwUuid.Zero)) return true;
for(int i = 0; i < lToDelete.Count; ++i) for(int i = 0; i < lToDelete.Count; ++i)
{ {
if(lToDelete[i].EqualsValue(pwUuid)) if(lToDelete[i].Equals(pwUuid))
{ {
lToDelete.RemoveAt(i); lToDelete.RemoveAt(i);
break; break;

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@ using System.Diagnostics;
using ModernKeePassLib.Delegates; using ModernKeePassLib.Delegates;
using ModernKeePassLib.Interfaces; using ModernKeePassLib.Interfaces;
using ModernKeePassLib.Serialization;
namespace ModernKeePassLib namespace ModernKeePassLib
{ {
@@ -44,6 +45,9 @@ namespace ModernKeePassLib
/// </summary> /// </summary>
public const string ShortProductName = "KeePass"; public const string ShortProductName = "KeePass";
internal const string UnixName = "keepass2";
internal const string ResClass = "KeePass2"; // With initial capital
/// <summary> /// <summary>
/// Version, encoded as 32-bit unsigned integer. /// Version, encoded as 32-bit unsigned integer.
/// 2.00 = 0x02000000, 2.01 = 0x02000100, ..., 2.18 = 0x02010800. /// 2.00 = 0x02000000, 2.01 = 0x02000100, ..., 2.18 = 0x02010800.
@@ -51,20 +55,20 @@ namespace ModernKeePassLib
/// e.g. 2.19 = 0x02130000. /// e.g. 2.19 = 0x02130000.
/// It is highly recommended to use <c>FileVersion64</c> instead. /// It is highly recommended to use <c>FileVersion64</c> instead.
/// </summary> /// </summary>
public const uint Version32 = 0x02130000; public const uint Version32 = 0x021C0000;
/// <summary> /// <summary>
/// Version, encoded as 64-bit unsigned integer /// Version, encoded as 64-bit unsigned integer
/// (component-wise, 16 bits per component). /// (component-wise, 16 bits per component).
/// </summary> /// </summary>
public const ulong FileVersion64 = 0x0002001300000000UL; public const ulong FileVersion64 = 0x0002001C00000000UL;
/// <summary> /// <summary>
/// Version, encoded as string. /// Version, encoded as string.
/// </summary> /// </summary>
public const string VersionString = "2.19"; public const string VersionString = "2.28";
public const string Copyright = @"Copyright <EFBFBD> 2003-2012 Dominik Reichl"; public const string Copyright = @"Copyright © 2003-2014 Dominik Reichl";
/// <summary> /// <summary>
/// Product website URL. Terminated by a forward slash. /// Product website URL. Terminated by a forward slash.
@@ -216,7 +220,7 @@ namespace ModernKeePassLib
} }
} }
#pragma warning disable 1591 // Missing XML comments warning // #pragma warning disable 1591 // Missing XML comments warning
/// <summary> /// <summary>
/// Search parameters for group and entry searches. /// Search parameters for group and entry searches.
/// </summary> /// </summary>
@@ -314,10 +318,11 @@ namespace ModernKeePassLib
set { m_bSearchInTags = value; } set { m_bSearchInTags = value; }
} }
#if PCL || KeePassRT
//Bert TODO: Check if using CurrentCultureIgnoreCase makes sense. private StringComparison m_scType = StringComparison.OrdinalIgnoreCase;
private StringComparison m_scType = StringComparison.CurrentCultureIgnoreCase; #else
//private StringComparison m_scType = StringComparison.InvariantCultureIgnoreCase; private StringComparison m_scType = StringComparison.InvariantCultureIgnoreCase;
#endif
/// <summary> /// <summary>
/// String comparison type. Specifies the condition when the specified /// String comparison type. Specifies the condition when the specified
/// text matches a group/entry string. /// text matches a group/entry string.
@@ -405,9 +410,9 @@ namespace ModernKeePassLib
return (SearchParameters)this.MemberwiseClone(); return (SearchParameters)this.MemberwiseClone();
} }
} }
#pragma warning restore 1591 // Missing XML comments warning // #pragma warning restore 1591 // Missing XML comments warning
#pragma warning disable 1591 // Missing XML comments warning // #pragma warning disable 1591 // Missing XML comments warning
/// <summary> /// <summary>
/// Memory protection configuration structure (for default fields). /// Memory protection configuration structure (for default fields).
/// </summary> /// </summary>
@@ -437,7 +442,7 @@ namespace ModernKeePassLib
return false; return false;
} }
} }
#pragma warning restore 1591 // Missing XML comments warning // #pragma warning restore 1591 // Missing XML comments warning
public sealed class ObjectTouchedEventArgs : EventArgs public sealed class ObjectTouchedEventArgs : EventArgs
{ {
@@ -458,4 +463,24 @@ namespace ModernKeePassLib
m_bParentsTouched = bParentsTouched; m_bParentsTouched = bParentsTouched;
} }
} }
public sealed class IOAccessEventArgs : EventArgs
{
private IOConnectionInfo m_ioc;
public IOConnectionInfo IOConnectionInfo { get { return m_ioc; } }
private IOConnectionInfo m_ioc2;
public IOConnectionInfo IOConnectionInfo2 { get { return m_ioc2; } }
private IOAccessType m_t;
public IOAccessType Type { get { return m_t; } }
public IOAccessEventArgs(IOConnectionInfo ioc, IOConnectionInfo ioc2,
IOAccessType t)
{
m_ioc = ioc;
m_ioc2 = ioc2;
m_t = t;
}
}
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -19,7 +19,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Xml;
using Windows.UI;
using ModernKeePassLib.Collections; using ModernKeePassLib.Collections;
using ModernKeePassLib.Interfaces; using ModernKeePassLib.Interfaces;
using ModernKeePassLib.Security; using ModernKeePassLib.Security;
@@ -27,12 +29,12 @@ using ModernKeePassLib.Utility;
namespace ModernKeePassLib namespace ModernKeePassLib
{ {
/// <summary> /// <summary>
/// A class representing a password entry. A password entry consists of several /// A class representing a password entry. A password entry consists of several
/// fields like title, user name, password, etc. Each password entry has a /// fields like title, user name, password, etc. Each password entry has a
/// unique ID (UUID). /// unique ID (UUID).
/// </summary> /// </summary>
public sealed class PwEntry : ITimeLogger, IStructureItem, IDeepCloneable<PwEntry> public sealed class PwEntry : ITimeLogger, IStructureItem, IDeepCloneable<PwEntry>
{ {
private PwUuid m_uuid = PwUuid.Zero; private PwUuid m_uuid = PwUuid.Zero;
private PwGroup m_pParentGroup = null; private PwGroup m_pParentGroup = null;
@@ -46,9 +48,8 @@ namespace ModernKeePassLib
private PwIcon m_pwIcon = PwIcon.Key; private PwIcon m_pwIcon = PwIcon.Key;
private PwUuid m_pwCustomIconID = PwUuid.Zero; private PwUuid m_pwCustomIconID = PwUuid.Zero;
private WinRTAdaptors.Color m_clrForeground = WinRTAdaptors.Color.Empty; private Color m_clrForeground;
private WinRTAdaptors.Color m_clrBackground = WinRTAdaptors.Color.Empty; private Color m_clrBackground;
private DateTime m_tCreation = PwDefs.DtDefaultNow; private DateTime m_tCreation = PwDefs.DtDefaultNow;
private DateTime m_tLastMod = PwDefs.DtDefaultNow; private DateTime m_tLastMod = PwDefs.DtDefaultNow;
@@ -81,7 +82,7 @@ namespace ModernKeePassLib
{ {
get { return m_pParentGroup; } get { return m_pParentGroup; }
/// Plugins: use <c>PwGroup.AddEntry</c> instead. // Plugins: use <c>PwGroup.AddEntry</c> instead.
internal set { m_pParentGroup = value; } internal set { m_pParentGroup = value; }
} }
@@ -173,7 +174,7 @@ namespace ModernKeePassLib
/// <summary> /// <summary>
/// Get or set the foreground color of this entry. /// Get or set the foreground color of this entry.
/// </summary> /// </summary>
public WinRTAdaptors.Color ForegroundColor public Color ForegroundColor
{ {
get { return m_clrForeground; } get { return m_clrForeground; }
set { m_clrForeground = value; } set { m_clrForeground = value; }
@@ -182,7 +183,7 @@ namespace ModernKeePassLib
/// <summary> /// <summary>
/// Get or set the background color of this entry. /// Get or set the background color of this entry.
/// </summary> /// </summary>
public WinRTAdaptors.Color BackgroundColor public Color BackgroundColor
{ {
get { return m_clrBackground; } get { return m_clrBackground; }
set { m_clrBackground = value; } set { m_clrBackground = value; }
@@ -197,15 +198,6 @@ namespace ModernKeePassLib
set { m_tCreation = value; } set { m_tCreation = value; }
} }
/// <summary>
/// The date/time when this entry was last accessed (read).
/// </summary>
public DateTime LastAccessTime
{
get { return m_tLastAccess; }
set { m_tLastAccess = value; }
}
/// <summary> /// <summary>
/// The date/time when this entry was last modified. /// The date/time when this entry was last modified.
/// </summary> /// </summary>
@@ -215,6 +207,15 @@ namespace ModernKeePassLib
set { m_tLastMod = value; } set { m_tLastMod = value; }
} }
/// <summary>
/// The date/time when this entry was last accessed (read).
/// </summary>
public DateTime LastAccessTime
{
get { return m_tLastAccess; }
set { m_tLastAccess = value; }
}
/// <summary> /// <summary>
/// The date/time when this entry expires. Use the <c>Expires</c> property /// The date/time when this entry expires. Use the <c>Expires</c> property
/// to specify if the entry does actually expire or not. /// to specify if the entry does actually expire or not.
@@ -402,10 +403,6 @@ namespace ModernKeePassLib
public bool EqualsEntry(PwEntry pe, PwCompareOptions pwOpt, public bool EqualsEntry(PwEntry pe, PwCompareOptions pwOpt,
MemProtCmpMode mpCmpStr) MemProtCmpMode mpCmpStr)
{ {
Debug.Assert(false, "not yet implemented");
return false;
#if TODO
if(pe == null) { Debug.Assert(false); return false; } if(pe == null) { Debug.Assert(false); return false; }
bool bNeEqStd = ((pwOpt & PwCompareOptions.NullEmptyEquivStd) != bool bNeEqStd = ((pwOpt & PwCompareOptions.NullEmptyEquivStd) !=
@@ -415,7 +412,7 @@ namespace ModernKeePassLib
bool bIgnoreLastMod = ((pwOpt & PwCompareOptions.IgnoreLastMod) != bool bIgnoreLastMod = ((pwOpt & PwCompareOptions.IgnoreLastMod) !=
PwCompareOptions.None); PwCompareOptions.None);
if(!m_uuid.EqualsValue(pe.m_uuid)) return false; if(!m_uuid.Equals(pe.m_uuid)) return false;
if((pwOpt & PwCompareOptions.IgnoreParentGroup) == PwCompareOptions.None) if((pwOpt & PwCompareOptions.IgnoreParentGroup) == PwCompareOptions.None)
{ {
if(m_pParentGroup != pe.m_pParentGroup) return false; if(m_pParentGroup != pe.m_pParentGroup) return false;
@@ -458,7 +455,7 @@ namespace ModernKeePassLib
} }
if(m_pwIcon != pe.m_pwIcon) return false; if(m_pwIcon != pe.m_pwIcon) return false;
if(!m_pwCustomIconID.EqualsValue(pe.m_pwCustomIconID)) return false; if(!m_pwCustomIconID.Equals(pe.m_pwCustomIconID)) return false;
if(m_clrForeground != pe.m_clrForeground) return false; if(m_clrForeground != pe.m_clrForeground) return false;
if(m_clrBackground != pe.m_clrBackground) return false; if(m_clrBackground != pe.m_clrBackground) return false;
@@ -479,7 +476,6 @@ namespace ModernKeePassLib
} }
return true; return true;
#endif
} }
/// <summary> /// <summary>
@@ -497,10 +493,12 @@ namespace ModernKeePassLib
{ {
Debug.Assert(peTemplate != null); if(peTemplate == null) throw new ArgumentNullException("peTemplate"); Debug.Assert(peTemplate != null); if(peTemplate == null) throw new ArgumentNullException("peTemplate");
if(bOnlyIfNewer && (peTemplate.m_tLastMod < m_tLastMod)) return; if(bOnlyIfNewer && (TimeUtil.Compare(peTemplate.m_tLastMod, m_tLastMod,
true) < 0))
return;
// Template UUID should be the same as the current one // Template UUID should be the same as the current one
Debug.Assert(m_uuid.EqualsValue(peTemplate.m_uuid)); Debug.Assert(m_uuid.Equals(peTemplate.m_uuid));
m_uuid = peTemplate.m_uuid; m_uuid = peTemplate.m_uuid;
if(bAssignLocationChanged) if(bAssignLocationChanged)
@@ -695,7 +693,7 @@ namespace ModernKeePassLib
for(uint u = 0; u < m_listHistory.UCount; ++u) for(uint u = 0; u < m_listHistory.UCount; ++u)
{ {
PwEntry pe = m_listHistory.GetAt(u); PwEntry pe = m_listHistory.GetAt(u);
if(pe.LastModificationTime < dtMin) if(TimeUtil.Compare(pe.LastModificationTime, dtMin, true) < 0)
{ {
idxRemove = u; idxRemove = u;
dtMin = pe.LastModificationTime; dtMin = pe.LastModificationTime;
@@ -847,6 +845,24 @@ namespace ModernKeePassLib
} }
} }
} }
public void SetCreatedNow()
{
DateTime dt = DateTime.Now;
m_tCreation = dt;
m_tLastAccess = dt;
}
public PwEntry Duplicate()
{
PwEntry pe = CloneDeep();
pe.SetUuid(new PwUuid(true), true);
pe.SetCreatedNow();
return pe;
}
} }
public sealed class PwEntryComparer : IComparer<PwEntry> public sealed class PwEntryComparer : IComparer<PwEntry>
@@ -867,13 +883,15 @@ namespace ModernKeePassLib
public int Compare(PwEntry a, PwEntry b) public int Compare(PwEntry a, PwEntry b)
{ {
Debug.Assert(false, "not yet implemented");
return 0;
#if TODO
string strA = a.Strings.ReadSafe(m_strFieldName); string strA = a.Strings.ReadSafe(m_strFieldName);
string strB = b.Strings.ReadSafe(m_strFieldName); string strB = b.Strings.ReadSafe(m_strFieldName);
if(m_bCompareNaturally) return StrUtil.CompareNaturally(strA, strB); if(m_bCompareNaturally) return StrUtil.CompareNaturally(strA, strB);
#if PCL || KeePassRT
return string.Compare(strA, strB, m_bCaseInsensitive ?
StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture);
#else
return string.Compare(strA, strB, m_bCaseInsensitive); return string.Compare(strA, strB, m_bCaseInsensitive);
#endif #endif
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -65,6 +65,8 @@ namespace ModernKeePassLib
/// </summary> /// </summary>
public enum PwMergeMethod public enum PwMergeMethod
{ {
// Do not change the explicitly assigned values, otherwise
// serialization (e.g. of Ecas triggers) breaks
None = 0, None = 0,
OverwriteExisting = 1, OverwriteExisting = 1,
KeepExisting = 2, KeepExisting = 2,
@@ -202,6 +204,67 @@ namespace ModernKeePassLib
IgnoreHistory = 0x10, IgnoreHistory = 0x10,
IgnoreLastBackup = 0x20, IgnoreLastBackup = 0x20,
// For groups:
PropertiesOnly = 0x40,
IgnoreTimes = (IgnoreLastAccess | IgnoreLastMod) IgnoreTimes = (IgnoreLastAccess | IgnoreLastMod)
} }
public enum IOAccessType
{
None = 0,
/// <summary>
/// The IO connection is being opened for reading.
/// </summary>
Read = 1,
/// <summary>
/// The IO connection is being opened for writing.
/// </summary>
Write = 2,
/// <summary>
/// The IO connection is being opened for testing
/// whether a file/object exists.
/// </summary>
Exists = 3,
/// <summary>
/// The IO connection is being opened for deleting a file/object.
/// </summary>
Delete = 4,
/// <summary>
/// The IO connection is being opened for renaming/moving a file/object.
/// </summary>
Move = 5
}
// public enum PwLogicalOp
// {
// None = 0,
// Or = 1,
// And = 2,
// NOr = 3,
// NAnd = 4
// }
[Flags]
public enum AppRunFlags
{
None = 0,
GetStdOutput = 1,
WaitForExit = 2,
// This flag prevents any handles being garbage-collected
// before the started process has terminated, without
// blocking the current thread;
// https://sourceforge.net/p/keepass/patches/84/
GCKeepAlive = 4,
// https://sourceforge.net/p/keepass/patches/85/
DoEvents = 8,
DisableForms = 16
}
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -137,7 +137,7 @@ namespace ModernKeePassLib
{ {
get { return m_pParentGroup; } get { return m_pParentGroup; }
/// Plugins: use <c>PwGroup.AddGroup</c> instead. // Plugins: use <c>PwGroup.AddGroup</c> instead.
internal set { Debug.Assert(value != this); m_pParentGroup = value; } internal set { Debug.Assert(value != this); m_pParentGroup = value; }
} }
@@ -352,9 +352,9 @@ namespace ModernKeePassLib
pg.m_pwCustomIconID = m_pwCustomIconID; pg.m_pwCustomIconID = m_pwCustomIconID;
pg.m_tCreation = m_tCreation; pg.m_tCreation = m_tCreation;
pg.m_tExpire = m_tExpire;
pg.m_tLastAccess = m_tLastAccess;
pg.m_tLastMod = m_tLastMod; pg.m_tLastMod = m_tLastMod;
pg.m_tLastAccess = m_tLastAccess;
pg.m_tExpire = m_tExpire;
pg.m_bExpires = m_bExpires; pg.m_bExpires = m_bExpires;
pg.m_uUsageCount = m_uUsageCount; pg.m_uUsageCount = m_uUsageCount;
@@ -363,6 +363,9 @@ namespace ModernKeePassLib
pg.m_strDefaultAutoTypeSequence = m_strDefaultAutoTypeSequence; pg.m_strDefaultAutoTypeSequence = m_strDefaultAutoTypeSequence;
pg.m_bEnableAutoType = m_bEnableAutoType;
pg.m_bEnableSearching = m_bEnableSearching;
pg.m_pwLastTopVisibleEntry = m_pwLastTopVisibleEntry; pg.m_pwLastTopVisibleEntry = m_pwLastTopVisibleEntry;
return pg; return pg;
@@ -385,6 +388,76 @@ namespace ModernKeePassLib
return pg; return pg;
} }
public bool EqualsGroup(PwGroup pg, PwCompareOptions pwOpt,
MemProtCmpMode mpCmpStr)
{
if(pg == null) { Debug.Assert(false); return false; }
bool bIgnoreLastAccess = ((pwOpt & PwCompareOptions.IgnoreLastAccess) !=
PwCompareOptions.None);
bool bIgnoreLastMod = ((pwOpt & PwCompareOptions.IgnoreLastMod) !=
PwCompareOptions.None);
if(!m_uuid.Equals(pg.m_uuid)) return false;
if((pwOpt & PwCompareOptions.IgnoreParentGroup) == PwCompareOptions.None)
{
if(m_pParentGroup != pg.m_pParentGroup) return false;
if(!bIgnoreLastMod && (m_tParentGroupLastMod != pg.m_tParentGroupLastMod))
return false;
}
if(m_strName != pg.m_strName) return false;
if(m_strNotes != pg.m_strNotes) return false;
if(m_pwIcon != pg.m_pwIcon) return false;
if(!m_pwCustomIconID.Equals(pg.m_pwCustomIconID)) return false;
if(m_tCreation != pg.m_tCreation) return false;
if(!bIgnoreLastMod && (m_tLastMod != pg.m_tLastMod)) return false;
if(!bIgnoreLastAccess && (m_tLastAccess != pg.m_tLastAccess)) return false;
if(m_tExpire != pg.m_tExpire) return false;
if(m_bExpires != pg.m_bExpires) return false;
if(!bIgnoreLastAccess && (m_uUsageCount != pg.m_uUsageCount)) return false;
// if(m_bIsExpanded != pg.m_bIsExpanded) return false;
if(m_strDefaultAutoTypeSequence != pg.m_strDefaultAutoTypeSequence) return false;
if(m_bEnableAutoType.HasValue != pg.m_bEnableAutoType.HasValue) return false;
if(m_bEnableAutoType.HasValue)
{
if(m_bEnableAutoType.Value != pg.m_bEnableAutoType.Value) return false;
}
if(m_bEnableSearching.HasValue != pg.m_bEnableSearching.HasValue) return false;
if(m_bEnableSearching.HasValue)
{
if(m_bEnableSearching.Value != pg.m_bEnableSearching.Value) return false;
}
if(!m_pwLastTopVisibleEntry.Equals(pg.m_pwLastTopVisibleEntry)) return false;
if((pwOpt & PwCompareOptions.PropertiesOnly) == PwCompareOptions.None)
{
if(m_listEntries.UCount != pg.m_listEntries.UCount) return false;
for(uint u = 0; u < m_listEntries.UCount; ++u)
{
PwEntry peA = m_listEntries.GetAt(u);
PwEntry peB = pg.m_listEntries.GetAt(u);
if(!peA.EqualsEntry(peB, pwOpt, mpCmpStr)) return false;
}
if(m_listGroups.UCount != pg.m_listGroups.UCount) return false;
for(uint u = 0; u < m_listGroups.UCount; ++u)
{
PwGroup pgA = m_listGroups.GetAt(u);
PwGroup pgB = pg.m_listGroups.GetAt(u);
if(!pgA.EqualsGroup(pgB, pwOpt, mpCmpStr)) return false;
}
}
return true;
}
/// <summary> /// <summary>
/// Assign properties to the current group based on a template group. /// Assign properties to the current group based on a template group.
/// </summary> /// </summary>
@@ -398,10 +471,12 @@ namespace ModernKeePassLib
{ {
Debug.Assert(pgTemplate != null); if(pgTemplate == null) throw new ArgumentNullException("pgTemplate"); Debug.Assert(pgTemplate != null); if(pgTemplate == null) throw new ArgumentNullException("pgTemplate");
if(bOnlyIfNewer && (pgTemplate.m_tLastMod < m_tLastMod)) return; if(bOnlyIfNewer && (TimeUtil.Compare(pgTemplate.m_tLastMod, m_tLastMod,
true) < 0))
return;
// Template UUID should be the same as the current one // Template UUID should be the same as the current one
Debug.Assert(m_uuid.EqualsValue(pgTemplate.m_uuid)); Debug.Assert(m_uuid.Equals(pgTemplate.m_uuid));
m_uuid = pgTemplate.m_uuid; m_uuid = pgTemplate.m_uuid;
if(bAssignLocationChanged) if(bAssignLocationChanged)
@@ -422,6 +497,9 @@ namespace ModernKeePassLib
m_strDefaultAutoTypeSequence = pgTemplate.m_strDefaultAutoTypeSequence; m_strDefaultAutoTypeSequence = pgTemplate.m_strDefaultAutoTypeSequence;
m_bEnableAutoType = pgTemplate.m_bEnableAutoType;
m_bEnableSearching = pgTemplate.m_bEnableSearching;
m_pwLastTopVisibleEntry = pgTemplate.m_pwLastTopVisibleEntry; m_pwLastTopVisibleEntry = pgTemplate.m_pwLastTopVisibleEntry;
} }
@@ -573,8 +651,6 @@ namespace ModernKeePassLib
/// <summary> /// <summary>
/// Pack all groups into one flat linked list of references (recursively). /// Pack all groups into one flat linked list of references (recursively).
/// Temporary IDs (<c>TemporaryID</c> field) and levels (<c>TemporaryLevel</c>)
/// are assigned automatically.
/// </summary> /// </summary>
/// <returns>Flat list of all groups.</returns> /// <returns>Flat list of all groups.</returns>
public LinkedList<PwGroup> GetFlatGroupList() public LinkedList<PwGroup> GetFlatGroupList()
@@ -671,6 +747,7 @@ namespace ModernKeePassLib
/// <param name="sp">Specifies the search method.</param> /// <param name="sp">Specifies the search method.</param>
/// <param name="listStorage">Entry list in which the search results will /// <param name="listStorage">Entry list in which the search results will
/// be stored.</param> /// be stored.</param>
/// <param name="slStatus">Optional status reporting object.</param>
public void SearchEntries(SearchParameters sp, PwObjectList<PwEntry> listStorage, public void SearchEntries(SearchParameters sp, PwObjectList<PwEntry> listStorage,
IStatusLogger slStatus) IStatusLogger slStatus)
{ {
@@ -743,9 +820,6 @@ namespace ModernKeePassLib
PwObjectList<PwEntry> listStorage, IStatusLogger slStatus, PwObjectList<PwEntry> listStorage, IStatusLogger slStatus,
ref ulong uCurEntries, ulong uTotalEntries) ref ulong uCurEntries, ulong uTotalEntries)
{ {
Debug.Assert(false, "not yet implemented");
return false;
#if TODO
SearchParameters sp = spIn.Clone(); SearchParameters sp = spIn.Clone();
if(sp.SearchString == null) { Debug.Assert(false); return true; } if(sp.SearchString == null) { Debug.Assert(false); return true; }
sp.SearchString = sp.SearchString.Trim(); sp.SearchString = sp.SearchString.Trim();
@@ -767,9 +841,15 @@ namespace ModernKeePassLib
Regex rx = null; Regex rx = null;
if(sp.RegularExpression) if(sp.RegularExpression)
{ {
#if PCL || KeePassRT
RegexOptions ro = RegexOptions.None;
#else
RegexOptions ro = RegexOptions.Compiled; RegexOptions ro = RegexOptions.Compiled;
#endif
if((sp.ComparisonMode == StringComparison.CurrentCultureIgnoreCase) || if((sp.ComparisonMode == StringComparison.CurrentCultureIgnoreCase) ||
#if !PCL && !KeePassRT
(sp.ComparisonMode == StringComparison.InvariantCultureIgnoreCase) || (sp.ComparisonMode == StringComparison.InvariantCultureIgnoreCase) ||
#endif
(sp.ComparisonMode == StringComparison.OrdinalIgnoreCase)) (sp.ComparisonMode == StringComparison.OrdinalIgnoreCase))
{ {
ro |= RegexOptions.IgnoreCase; ro |= RegexOptions.IgnoreCase;
@@ -880,7 +960,6 @@ namespace ModernKeePassLib
if(!PreOrderTraverseTree(null, eh)) return false; if(!PreOrderTraverseTree(null, eh)) return false;
uCurEntries = uLocalCurEntries; uCurEntries = uLocalCurEntries;
return true; return true;
#endif
} }
private static void SearchEvalAdd(SearchParameters sp, string strDataField, private static void SearchEvalAdd(SearchParameters sp, string strDataField,
@@ -942,6 +1021,30 @@ namespace ModernKeePassLib
return vTags; return vTags;
} }
#if !KeePassLibSD
public IDictionary<string, uint> BuildEntryTagsDict(bool bSort)
{
IDictionary<string, uint> d;
if(!bSort) d = new Dictionary<string, uint>(StrUtil.CaseIgnoreComparer);
else d = new SortedDictionary<string, uint>(StrUtil.CaseIgnoreComparer);
EntryHandler eh = delegate(PwEntry pe)
{
foreach(string strTag in pe.Tags)
{
uint u;
if(d.TryGetValue(strTag, out u)) d[strTag] = u + 1;
else d[strTag] = 1;
}
return true;
};
TraverseTree(TraversalMethod.PreOrder, null, eh);
return d;
}
#endif
public void FindEntriesByTag(string strTag, PwObjectList<PwEntry> listStorage, public void FindEntriesByTag(string strTag, PwObjectList<PwEntry> listStorage,
bool bSearchRecursive) bool bSearchRecursive)
{ {
@@ -976,7 +1079,7 @@ namespace ModernKeePassLib
public PwGroup FindGroup(PwUuid uuid, bool bSearchRecursive) public PwGroup FindGroup(PwUuid uuid, bool bSearchRecursive)
{ {
// Do not assert on PwUuid.Zero // Do not assert on PwUuid.Zero
if(m_uuid.EqualsValue(uuid)) return this; if(m_uuid.Equals(uuid)) return this;
if(bSearchRecursive) if(bSearchRecursive)
{ {
@@ -991,7 +1094,7 @@ namespace ModernKeePassLib
{ {
foreach(PwGroup pg in m_listGroups) foreach(PwGroup pg in m_listGroups)
{ {
if(pg.m_uuid.EqualsValue(uuid)) if(pg.m_uuid.Equals(uuid))
return pg; return pg;
} }
} }
@@ -1055,7 +1158,7 @@ namespace ModernKeePassLib
{ {
foreach(PwEntry pe in m_listEntries) foreach(PwEntry pe in m_listEntries)
{ {
if(pe.Uuid.EqualsValue(uuid)) return pe; if(pe.Uuid.Equals(uuid)) return pe;
} }
if(bSearchRecursive) if(bSearchRecursive)
@@ -1085,6 +1188,8 @@ namespace ModernKeePassLib
/// </summary> /// </summary>
/// <param name="strSeparator">String that separates the group /// <param name="strSeparator">String that separates the group
/// names.</param> /// names.</param>
/// <param name="bIncludeTopMostGroup">Specifies whether the returned
/// path starts with the topmost group.</param>
/// <returns>Full path of the group.</returns> /// <returns>Full path of the group.</returns>
public string GetFullPath(string strSeparator, bool bIncludeTopMostGroup) public string GetFullPath(string strSeparator, bool bIncludeTopMostGroup)
{ {
@@ -1155,6 +1260,7 @@ namespace ModernKeePassLib
} }
} }
#if !KeePassLibSD
/// <summary> /// <summary>
/// Find/create a subtree of groups. /// Find/create a subtree of groups.
/// </summary> /// </summary>
@@ -1168,11 +1274,23 @@ namespace ModernKeePassLib
public PwGroup FindCreateSubTree(string strTree, char[] vSeparators, public PwGroup FindCreateSubTree(string strTree, char[] vSeparators,
bool bAllowCreate) bool bAllowCreate)
{
if(vSeparators == null) { Debug.Assert(false); vSeparators = new char[0]; }
string[] v = new string[vSeparators.Length];
for(int i = 0; i < vSeparators.Length; ++i)
v[i] = new string(vSeparators[i], 1);
return FindCreateSubTree(strTree, v, bAllowCreate);
}
public PwGroup FindCreateSubTree(string strTree, string[] vSeparators,
bool bAllowCreate)
{ {
Debug.Assert(strTree != null); if(strTree == null) return this; Debug.Assert(strTree != null); if(strTree == null) return this;
if(strTree.Length == 0) return this; if(strTree.Length == 0) return this;
string[] vGroups = strTree.Split(vSeparators); string[] vGroups = strTree.Split(vSeparators, StringSplitOptions.None);
if((vGroups == null) || (vGroups.Length == 0)) return this; if((vGroups == null) || (vGroups.Length == 0)) return this;
PwGroup pgContainer = this; PwGroup pgContainer = this;
@@ -1203,6 +1321,7 @@ namespace ModernKeePassLib
return pgContainer; return pgContainer;
} }
#endif
/// <summary> /// <summary>
/// Get the level of the group (i.e. the number of parent groups). /// Get the level of the group (i.e. the number of parent groups).
@@ -1426,6 +1545,69 @@ namespace ModernKeePassLib
} }
m_listGroups.Clear(); m_listGroups.Clear();
} }
internal List<PwGroup> GetTopSearchSkippedGroups()
{
List<PwGroup> l = new List<PwGroup>();
if(!GetSearchingEnabledInherited()) l.Add(this);
else GetTopSearchSkippedGroupsRec(l);
return l;
}
private void GetTopSearchSkippedGroupsRec(List<PwGroup> l)
{
if(m_bEnableSearching.HasValue && !m_bEnableSearching.Value)
{
l.Add(this);
return;
}
else { Debug.Assert(GetSearchingEnabledInherited()); }
foreach(PwGroup pgSub in m_listGroups)
pgSub.GetTopSearchSkippedGroupsRec(l);
}
public void SetCreatedNow(bool bRecursive)
{
DateTime dt = DateTime.Now;
m_tCreation = dt;
m_tLastAccess = dt;
if(!bRecursive) return;
GroupHandler gh = delegate(PwGroup pg)
{
pg.m_tCreation = dt;
pg.m_tLastAccess = dt;
return true;
};
EntryHandler eh = delegate(PwEntry pe)
{
pe.CreationTime = dt;
pe.LastAccessTime = dt;
return true;
};
TraverseTree(TraversalMethod.PreOrder, gh, eh);
}
public PwGroup Duplicate()
{
PwGroup pg = CloneDeep();
pg.Uuid = new PwUuid(true);
pg.CreateNewItemUuids(true, true, true);
pg.SetCreatedNow(true);
pg.TakeOwnership(true, true, true);
return pg;
}
} }
public sealed class PwGroupComparer : IComparer<PwGroup> public sealed class PwGroupComparer : IComparer<PwGroup>

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -18,6 +18,7 @@
*/ */
using System; using System;
using System.Collections.Generic;
using System.Xml; using System.Xml;
using System.Diagnostics; using System.Diagnostics;
@@ -27,10 +28,10 @@ namespace ModernKeePassLib
{ {
// [ImmutableObject(true)] // [ImmutableObject(true)]
/// <summary> /// <summary>
/// Represents an UUID of a password entry or group. Once created, <c>PwUuid</c> /// Represents an UUID of a password entry or group. Once created,
/// objects aren't modifyable anymore (immutable). /// <c>PwUuid</c> objects aren't modifyable anymore (immutable).
/// </summary> /// </summary>
public sealed class PwUuid public sealed class PwUuid : IComparable<PwUuid>, IEquatable<PwUuid>
{ {
/// <summary> /// <summary>
/// Standard size in bytes of a UUID. /// Standard size in bytes of a UUID.
@@ -40,9 +41,9 @@ namespace ModernKeePassLib
/// <summary> /// <summary>
/// Zero UUID (all bytes are zero). /// Zero UUID (all bytes are zero).
/// </summary> /// </summary>
public static readonly PwUuid Zero = new PwUuid(); public static readonly PwUuid Zero = new PwUuid(false);
private byte[] m_pbUuid = new byte[UuidSize]; private byte[] m_pbUuid = null; // Never null after constructor
/// <summary> /// <summary>
/// Get the 16 UUID bytes. /// Get the 16 UUID bytes.
@@ -52,14 +53,6 @@ namespace ModernKeePassLib
get { return m_pbUuid; } get { return m_pbUuid; }
} }
/// <summary>
/// Construct a new UUID object. Its value is initialized to zero.
/// </summary>
private PwUuid()
{
SetZero();
}
/// <summary> /// <summary>
/// Construct a new UUID object. /// Construct a new UUID object.
/// </summary> /// </summary>
@@ -88,38 +81,95 @@ namespace ModernKeePassLib
/// otherwise it returns <c>false</c>.</returns> /// otherwise it returns <c>false</c>.</returns>
private void CreateNew() private void CreateNew()
{ {
Debug.Assert(m_pbUuid == null); // Only call from constructor
while(true) while(true)
{ {
m_pbUuid = Guid.NewGuid().ToByteArray(); m_pbUuid = Guid.NewGuid().ToByteArray();
if((m_pbUuid == null) || (m_pbUuid.Length != UuidSize)) if((m_pbUuid == null) || (m_pbUuid.Length != (int)UuidSize))
{
Debug.Assert(false);
throw new InvalidOperationException(); throw new InvalidOperationException();
}
// Zero is a reserved value -- do not generate Zero // Zero is a reserved value -- do not generate Zero
if(this.EqualsValue(PwUuid.Zero) == false) if(!Equals(PwUuid.Zero)) break;
break; Debug.Assert(false);
} }
} }
/// <summary> private void SetValue(byte[] uuidBytes)
/// Compare this UUID with another. {
/// </summary> Debug.Assert((uuidBytes != null) && (uuidBytes.Length == (int)UuidSize));
/// <param name="uuid">Second UUID object.</param> if(uuidBytes == null) throw new ArgumentNullException("uuidBytes");
/// <returns>Returns <c>true</c> if both PwUuid object contain the same if(uuidBytes.Length != (int)UuidSize) throw new ArgumentException();
/// value, otherwise <c>false</c> is returned.</returns>
Debug.Assert(m_pbUuid == null); // Only call from constructor
m_pbUuid = new byte[UuidSize];
Array.Copy(uuidBytes, m_pbUuid, (int)UuidSize);
}
private void SetZero()
{
Debug.Assert(m_pbUuid == null); // Only call from constructor
m_pbUuid = new byte[UuidSize];
// Array.Clear(m_pbUuid, 0, (int)UuidSize);
#if DEBUG
List<byte> l = new List<byte>(m_pbUuid);
Debug.Assert(l.TrueForAll(bt => (bt == 0)));
#endif
}
[Obsolete]
public bool EqualsValue(PwUuid uuid) public bool EqualsValue(PwUuid uuid)
{ {
Debug.Assert(uuid != null); return Equals(uuid);
if(uuid == null) throw new ArgumentNullException("uuid"); }
for(int i = 0; i < UuidSize; ++i) public override bool Equals(object obj)
{
return Equals(obj as PwUuid);
}
public bool Equals(PwUuid other)
{
if(other == null) { Debug.Assert(false); return false; }
for(int i = 0; i < (int)UuidSize; ++i)
{ {
if(m_pbUuid[i] != uuid.m_pbUuid[i]) return false; if(m_pbUuid[i] != other.m_pbUuid[i]) return false;
} }
return true; return true;
} }
private int m_h = 0;
public override int GetHashCode()
{
if(m_h == 0)
m_h = (int)MemUtil.Hash32(m_pbUuid, 0, m_pbUuid.Length);
return m_h;
}
public int CompareTo(PwUuid other)
{
if(other == null)
{
Debug.Assert(false);
throw new ArgumentNullException("other");
}
for(int i = 0; i < (int)UuidSize; ++i)
{
if(m_pbUuid[i] < other.m_pbUuid[i]) return -1;
if(m_pbUuid[i] > other.m_pbUuid[i]) return 1;
}
return 0;
}
/// <summary> /// <summary>
/// Convert the UUID to its string representation. /// Convert the UUID to its string representation.
/// </summary> /// </summary>
@@ -129,29 +179,15 @@ namespace ModernKeePassLib
return MemUtil.ByteArrayToHexString(m_pbUuid); return MemUtil.ByteArrayToHexString(m_pbUuid);
} }
/// <summary> #if DEBUG
/// Set the UUID value. The input parameter will not be modified. public override string ToString()
/// </summary>
/// <param name="uuidBytes">UUID bytes. The byte array must contain
/// exactly <c>UUIDSize</c> bytes, otherwise the function will fail.</param>
private void SetValue(byte[] uuidBytes)
{ {
Debug.Assert((uuidBytes != null) && (uuidBytes.Length == UuidSize)); return ToHexString();
if(uuidBytes == null) throw new ArgumentNullException("uuidBytes");
if(uuidBytes.Length != UuidSize) throw new ArgumentException();
Array.Copy(uuidBytes, m_pbUuid, (int)UuidSize);
}
/// <summary>
/// Set the UUID value to zero.
/// </summary>
private void SetZero()
{
Array.Clear(m_pbUuid, 0, (int)UuidSize);
} }
#endif
} }
[Obsolete]
public sealed class PwUuidComparable : IComparable<PwUuidComparable> public sealed class PwUuidComparable : IComparable<PwUuidComparable>
{ {
private byte[] m_pbUuid = new byte[PwUuid.UuidSize]; private byte[] m_pbUuid = new byte[PwUuid.UuidSize];

View File

@@ -48,6 +48,7 @@ namespace ModernKeePassLib.Resources
m_strInvalidCompositeKeyHint = TryGetEx(dictNew, "InvalidCompositeKeyHint", m_strInvalidCompositeKeyHint); m_strInvalidCompositeKeyHint = TryGetEx(dictNew, "InvalidCompositeKeyHint", m_strInvalidCompositeKeyHint);
m_strInvalidDataWhileDecoding = TryGetEx(dictNew, "InvalidDataWhileDecoding", m_strInvalidDataWhileDecoding); m_strInvalidDataWhileDecoding = TryGetEx(dictNew, "InvalidDataWhileDecoding", m_strInvalidDataWhileDecoding);
m_strKeePass1xHint = TryGetEx(dictNew, "KeePass1xHint", m_strKeePass1xHint); m_strKeePass1xHint = TryGetEx(dictNew, "KeePass1xHint", m_strKeePass1xHint);
m_strKeyFileDbSel = TryGetEx(dictNew, "KeyFileDbSel", m_strKeyFileDbSel);
m_strMasterSeedLengthInvalid = TryGetEx(dictNew, "MasterSeedLengthInvalid", m_strMasterSeedLengthInvalid); m_strMasterSeedLengthInvalid = TryGetEx(dictNew, "MasterSeedLengthInvalid", m_strMasterSeedLengthInvalid);
m_strOldFormat = TryGetEx(dictNew, "OldFormat", m_strOldFormat); m_strOldFormat = TryGetEx(dictNew, "OldFormat", m_strOldFormat);
m_strTryAgainSecs = TryGetEx(dictNew, "TryAgainSecs", m_strTryAgainSecs); m_strTryAgainSecs = TryGetEx(dictNew, "TryAgainSecs", m_strTryAgainSecs);
@@ -78,6 +79,7 @@ namespace ModernKeePassLib.Resources
"InvalidCompositeKeyHint", "InvalidCompositeKeyHint",
"InvalidDataWhileDecoding", "InvalidDataWhileDecoding",
"KeePass1xHint", "KeePass1xHint",
"KeyFileDbSel",
"MasterSeedLengthInvalid", "MasterSeedLengthInvalid",
"OldFormat", "OldFormat",
"TryAgainSecs", "TryAgainSecs",
@@ -201,10 +203,10 @@ namespace ModernKeePassLib.Resources
} }
private static string m_strFileSaveCorruptionWarning = private static string m_strFileSaveCorruptionWarning =
@"The target file might be in a corrupted state. Please try saving again, and if that fails, save the database to a different location."; @"The target file might be corrupted. Please try saving again. If that fails, save the database to a different location.";
/// <summary> /// <summary>
/// Look up a localized string similar to /// Look up a localized string similar to
/// 'The target file might be in a corrupted state. Please try saving again, and if that fails, save the database to a different location.'. /// 'The target file might be corrupted. Please try saving again. If that fails, save the database to a different location.'.
/// </summary> /// </summary>
public static string FileSaveCorruptionWarning public static string FileSaveCorruptionWarning
{ {
@@ -332,6 +334,17 @@ namespace ModernKeePassLib.Resources
get { return m_strKeePass1xHint; } get { return m_strKeePass1xHint; }
} }
private static string m_strKeyFileDbSel =
@"Database files cannot be used as key files.";
/// <summary>
/// Look up a localized string similar to
/// 'Database files cannot be used as key files.'.
/// </summary>
public static string KeyFileDbSel
{
get { return m_strKeyFileDbSel; }
}
private static string m_strMasterSeedLengthInvalid = private static string m_strMasterSeedLengthInvalid =
@"The length of the master key seed is invalid!"; @"The length of the master key seed is invalid!";
/// <summary> /// <summary>

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -18,170 +18,307 @@
*/ */
using System; using System;
using System.Threading.Tasks; using System.Threading;
using System.Diagnostics;
using ModernKeePassLib.Utility;
using ModernKeePassLib.Cryptography; using ModernKeePassLib.Cryptography;
using Windows.Security.Cryptography; using ModernKeePassLib.Cryptography.Cipher;
using Windows.Security.Cryptography.DataProtection; using ModernKeePassLib.Utility;
using Windows.Storage.Streams;
#if KeePassLibSD #if KeePassLibSD
using ModernKeePassLibSD; using KeePassLibSD;
#endif #endif
namespace ModernKeePassLib.Security namespace ModernKeePassLib.Security
{ {
/// <summary> [Flags]
/// Represents a protected binary, i.e. a byte array that is encrypted public enum PbCryptFlags
/// in memory. A <c>ProtectedBinary</c> object is immutable and {
/// thread-safe. None = 0,
/// </summary> Encrypt = 1,
public sealed class ProtectedBinary : IEquatable<ProtectedBinary> Decrypt = 2
{ }
private static bool m_bProtectionSupported;
private IBuffer m_pbDataCrypted;
private DataProtectionProvider m_pProvider;
private bool m_bProtected;
/// <summary> public delegate void PbCryptDelegate(byte[] pbData, PbCryptFlags cf,
/// A flag specifying whether the <c>ProtectedBinary</c> object has long lID);
/// turned on in-memory protection or not.
/// </summary> /// <summary>
public bool IsProtected /// Represents a protected binary, i.e. a byte array that is encrypted
{ /// in memory. A <c>ProtectedBinary</c> object is immutable and
get /// thread-safe.
{ /// </summary>
Debug.Assert(false, "not yet implemented"); public sealed class ProtectedBinary : IEquatable<ProtectedBinary>
{
private const int BlockSize = 16;
private static PbCryptDelegate g_fExtCrypt = null;
/// <summary>
/// A plugin can provide a custom memory protection method
/// by assigning a non-null delegate to this property.
/// </summary>
public static PbCryptDelegate ExtCrypt
{
get { return g_fExtCrypt; }
set { g_fExtCrypt = value; }
}
// Local copy of the delegate that was used for encryption,
// in order to allow correct decryption even when the global
// delegate changes
private PbCryptDelegate m_fExtCrypt = null;
private enum PbMemProt
{
None = 0,
ProtectedMemory,
Salsa20,
ExtCrypt
}
// ProtectedMemory is supported only on Windows 2000 SP3 and higher
#if !KeePassLibSD
private static bool? g_bProtectedMemorySupported = null;
#endif
private static bool ProtectedMemorySupported
{
get
{
#if KeePassLibSD
return false;
#elif PCL
return false; return false;
#if TODO #else
return m_bProtected; bool? ob = g_bProtectedMemorySupported;
if(ob.HasValue) return ob.Value;
// Mono does not implement any encryption for ProtectedMemory;
// https://sourceforge.net/p/keepass/feature-requests/1907/
/*if(NativeLib.IsUnix())
{
g_bProtectedMemorySupported = false;
return false;
}*/
ob = false;
try // Test whether ProtectedMemory is supported
{
// BlockSize * 3 in order to test encryption for multiple
// blocks, but not introduce a power of 2 as factor
byte[] pb = new byte[ProtectedBinary.BlockSize * 3];
for(int i = 0; i < pb.Length; ++i) pb[i] = (byte)i;
ProtectedMemory.Protect(pb, MemoryProtectionScope.SameProcess);
for(int i = 0; i < pb.Length; ++i)
{
if(pb[i] != (byte)i) { ob = true; break; }
}
}
catch(Exception) { } // Windows 98 / ME
g_bProtectedMemorySupported = ob;
return ob.Value;
#endif #endif
} }
} }
/// <summary> private static long g_lCurID = 0;
/// Length of the stored data. private long m_lID;
/// </summary>
public uint Length
{
get
{
Debug.Assert(false, "not yet implemented"); private byte[] m_pbData; // Never null
return 0;
#if TODO // The real length of the data; this value can be different from
return m_uDataLen; // m_pbData.Length, as the length of m_pbData always is a multiple
// of BlockSize (required for ProtectedMemory)
private uint m_uDataLen;
private bool m_bProtected; // Protection requested by the caller
private PbMemProt m_mp = PbMemProt.None; // Actual protection
private object m_objSync = new object();
private static byte[] g_pbKey32 = null;
/// <summary>
/// A flag specifying whether the <c>ProtectedBinary</c> object has
/// turned on memory protection or not.
/// </summary>
public bool IsProtected
{
get { return m_bProtected; }
}
/// <summary>
/// Length of the stored data.
/// </summary>
public uint Length
{
get { return m_uDataLen; }
}
/// <summary>
/// Construct a new, empty protected binary data object.
/// Protection is disabled.
/// </summary>
public ProtectedBinary()
{
Init(false, new byte[0]);
}
/// <summary>
/// Construct a new protected binary data object.
/// </summary>
/// <param name="bEnableProtection">If this paremeter is <c>true</c>,
/// the data will be encrypted in memory. If it is <c>false</c>, the
/// data is stored in plain-text in the process memory.</param>
/// <param name="pbData">Value of the protected object.
/// The input parameter is not modified and
/// <c>ProtectedBinary</c> doesn't take ownership of the data,
/// i.e. the caller is responsible for clearing it.</param>
public ProtectedBinary(bool bEnableProtection, byte[] pbData)
{
Init(bEnableProtection, pbData);
}
/// <summary>
/// Construct a new protected binary data object. Copy the data from
/// a <c>XorredBuffer</c> object.
/// </summary>
/// <param name="bEnableProtection">Enable protection or not.</param>
/// <param name="xbProtected"><c>XorredBuffer</c> object used to
/// initialize the <c>ProtectedBinary</c> object.</param>
public ProtectedBinary(bool bEnableProtection, XorredBuffer xbProtected)
{
Debug.Assert(xbProtected != null);
if(xbProtected == null) throw new ArgumentNullException("xbProtected");
byte[] pb = xbProtected.ReadPlainText();
Init(bEnableProtection, pb);
MemUtil.ZeroByteArray(pb);
}
private void Init(bool bEnableProtection, byte[] pbData)
{
if(pbData == null) throw new ArgumentNullException("pbData");
#if KeePassLibSD
m_lID = ++g_lCurID;
#else
m_lID = Interlocked.Increment(ref g_lCurID);
#endif #endif
}
}
static ProtectedBinary() m_bProtected = bEnableProtection;
{ m_uDataLen = (uint)pbData.Length;
m_bProtectionSupported = true;
}
/// <summary> const int bs = ProtectedBinary.BlockSize;
/// Construct a new, empty protected binary data object. Protection int nBlocks = (int)m_uDataLen / bs;
/// is disabled. if((nBlocks * bs) < (int)m_uDataLen) ++nBlocks;
/// </summary> Debug.Assert((nBlocks * bs) >= (int)m_uDataLen);
public ProtectedBinary()
{
Init(false, new byte[0]);
}
/// <summary> m_pbData = new byte[nBlocks * bs];
/// Construct a new protected binary data object. Array.Copy(pbData, m_pbData, (int)m_uDataLen);
/// </summary>
/// <param name="bEnableProtection">If this paremeter is <c>true</c>,
/// the data will be encrypted in memory. If it is <c>false</c>, the
/// data is stored in plain-text in the process memory.</param>
/// <param name="pbData">Value of the protected object.
/// The input parameter is not modified and
/// <c>ProtectedBinary</c> doesn't take ownership of the data,
/// i.e. the caller is responsible for clearing it.</param>
public ProtectedBinary(bool bEnableProtection, byte[] pbData)
{
Init(bEnableProtection, pbData);
}
/// <summary> Encrypt();
/// Construct a new protected binary data object. Copy the data from }
/// a <c>XorredBuffer</c> object.
/// </summary>
/// <param name="bEnableProtection">Enable protection or not.</param>
/// <param name="xbProtected"><c>XorredBuffer</c> object used to
/// initialize the <c>ProtectedBinary</c> object.</param>
/// <exception cref="System.ArgumentNullException">Thrown if the input
/// parameter is <c>null</c>.</exception>
public ProtectedBinary(bool bEnableProtection, XorredBuffer xbProtected)
{
Debug.Assert(xbProtected != null); if (xbProtected == null) throw new ArgumentNullException("xbProtected");
byte[] pb = xbProtected.ReadPlainText(); private void Encrypt()
Init(bEnableProtection, pb); {
MemUtil.ZeroByteArray(pb); Debug.Assert(m_mp == PbMemProt.None);
}
private void Init(bool bEnableProtection, byte[] pbData) // Nothing to do if caller didn't request protection
{ if(!m_bProtected) return;
String strDescriptor = "LOCAL=user";
m_pProvider = new DataProtectionProvider(strDescriptor);
EncryptAsync(bEnableProtection, pbData); // ProtectedMemory.Protect throws for data size == 0
if(m_pbData.Length == 0) return;
} PbCryptDelegate f = g_fExtCrypt;
if(f != null)
{
f(m_pbData, PbCryptFlags.Encrypt, m_lID);
private void EncryptAsync(bool bEnableProtection, byte[] pbData) m_fExtCrypt = f;
{ m_mp = PbMemProt.ExtCrypt;
IBuffer dataUncrypted = CryptographicBuffer.CreateFromByteArray(pbData); return;
}
Task<IBuffer> task = m_pProvider.ProtectAsync(dataUncrypted).AsTask<IBuffer>(); #if !PCL
task.Wait(); if(ProtectedBinary.ProtectedMemorySupported)
{
ProtectedMemory.Protect(m_pbData, MemoryProtectionScope.SameProcess);
m_pbDataCrypted = task.Result; m_mp = PbMemProt.ProtectedMemory;
// TODO: Here the dataUncrypted buffer should be cleared. Now just count on GarbageCollection to destroy. return;
}
#endif
byte[] pbKey32 = g_pbKey32;
if(pbKey32 == null)
{
pbKey32 = CryptoRandom.Instance.GetRandomBytes(32);
} byte[] pbUpd = Interlocked.Exchange<byte[]>(ref g_pbKey32, pbKey32);
if(pbUpd != null) pbKey32 = pbUpd;
}
/// <summary> Salsa20Cipher s = new Salsa20Cipher(pbKey32,
/// Get a copy of the protected data as a byte array. BitConverter.GetBytes(m_lID));
/// Please note that the returned byte array is not protected and s.Encrypt(m_pbData, m_pbData.Length, true);
/// can therefore been read by any other application. s.Dispose();
/// Make sure that your clear it properly after usage. m_mp = PbMemProt.Salsa20;
/// </summary> }
/// <returns>Unprotected byte array. This is always a copy of the internal
/// protected data and can therefore be cleared safely.</returns>
public byte[] ReadData()
{
if (m_pbDataCrypted == null) return new byte[0];
// Decrypt the protected message specified on input. private void Decrypt()
{
if(m_pbData.Length == 0) return;
#if !PCL
if(m_mp == PbMemProt.ProtectedMemory)
ProtectedMemory.Unprotect(m_pbData, MemoryProtectionScope.SameProcess);
#endif
else if(m_mp == PbMemProt.Salsa20)
{
Salsa20Cipher s = new Salsa20Cipher(g_pbKey32,
BitConverter.GetBytes(m_lID));
s.Encrypt(m_pbData, m_pbData.Length, true);
s.Dispose();
}
else if(m_mp == PbMemProt.ExtCrypt)
m_fExtCrypt(m_pbData, PbCryptFlags.Decrypt, m_lID);
else { Debug.Assert(m_mp == PbMemProt.None); }
Task<IBuffer> task = m_pProvider.UnprotectAsync(m_pbDataCrypted).AsTask<IBuffer>(); m_mp = PbMemProt.None;
task.Wait(); }
IBuffer buffUnprotected = task.Result; /// <summary>
byte[] strClearText; /// Get a copy of the protected data as a byte array.
CryptographicBuffer.CopyToByteArray(buffUnprotected, out strClearText); /// Please note that the returned byte array is not protected and
return strClearText; /// can therefore been read by any other application.
/// Make sure that your clear it properly after usage.
/// </summary>
/// <returns>Unprotected byte array. This is always a copy of the internal
/// protected data and can therefore be cleared safely.</returns>
public byte[] ReadData()
{
if(m_uDataLen == 0) return new byte[0];
} byte[] pbReturn = new byte[m_uDataLen];
/// <summary> lock(m_objSync)
/// Read the protected data and return it protected with a sequence {
/// of bytes generated by a random stream. Decrypt();
/// </summary> Array.Copy(m_pbData, pbReturn, (int)m_uDataLen);
/// <param name="crsRandomSource">Random number source.</param> Encrypt();
/// <returns>Protected data.</returns> }
/// <exception cref="System.ArgumentNullException">Thrown if the input
/// parameter is <c>null</c>.</exception> return pbReturn;
public byte[] ReadXorredData(CryptoRandomStream crsRandomSource) }
{
Debug.Assert(false, "not yet implemented"); /// <summary>
return null; /// Read the protected data and return it protected with a sequence
#if TODO /// of bytes generated by a random stream.
/// </summary>
/// <param name="crsRandomSource">Random number source.</param>
public byte[] ReadXorredData(CryptoRandomStream crsRandomSource)
{
Debug.Assert(crsRandomSource != null); Debug.Assert(crsRandomSource != null);
if(crsRandomSource == null) throw new ArgumentNullException("crsRandomSource"); if(crsRandomSource == null) throw new ArgumentNullException("crsRandomSource");
@@ -189,20 +326,19 @@ namespace ModernKeePassLib.Security
uint uLen = (uint)pbData.Length; uint uLen = (uint)pbData.Length;
byte[] randomPad = crsRandomSource.GetRandomBytes(uLen); byte[] randomPad = crsRandomSource.GetRandomBytes(uLen);
Debug.Assert(randomPad.Length == uLen); Debug.Assert(randomPad.Length == pbData.Length);
for(uint i = 0; i < uLen; ++i) for(uint i = 0; i < uLen; ++i)
pbData[i] ^= randomPad[i]; pbData[i] ^= randomPad[i];
return pbData; return pbData;
#endif }
}
private int? m_hash = null;
public override int GetHashCode()
{
if(m_hash.HasValue) return m_hash.Value;
public override int GetHashCode()
{
Debug.Assert(false, "not yet implemented");
return 0;
#if TODO
int h = (m_bProtected ? 0x7B11D289 : 0); int h = (m_bProtected ? 0x7B11D289 : 0);
byte[] pb = ReadData(); byte[] pb = ReadData();
@@ -213,20 +349,17 @@ namespace ModernKeePassLib.Security
} }
MemUtil.ZeroByteArray(pb); MemUtil.ZeroByteArray(pb);
m_hash = h;
return h; return h;
#endif }
}
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return Equals(obj as ProtectedBinary); return Equals(obj as ProtectedBinary);
} }
public bool Equals(ProtectedBinary other) public bool Equals(ProtectedBinary other)
{ {
Debug.Assert(false, "not yet implemented");
return false;
#if TODO
if(other == null) return false; // No assert if(other == null) return false; // No assert
if(m_bProtected != other.m_bProtected) return false; if(m_bProtected != other.m_bProtected) return false;
@@ -243,7 +376,6 @@ namespace ModernKeePassLib.Security
#endif #endif
return bEq; return bEq;
#endif }
} }
}
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -23,10 +23,9 @@ using System.Diagnostics;
using ModernKeePassLib.Cryptography; using ModernKeePassLib.Cryptography;
using ModernKeePassLib.Utility; using ModernKeePassLib.Utility;
using System.Threading.Tasks;
#if KeePassLibSD #if KeePassLibSD
using ModernKeePassLibSD; using KeePassLibSD;
#endif #endif
// SecureString objects are limited to 65536 characters, don't use // SecureString objects are limited to 65536 characters, don't use
@@ -48,7 +47,7 @@ namespace ModernKeePassLib.Security
private bool m_bIsProtected; private bool m_bIsProtected;
private static ProtectedString m_psEmpty = new ProtectedString(); private static readonly ProtectedString m_psEmpty = new ProtectedString();
public static ProtectedString Empty public static ProtectedString Empty
{ {
get { return m_psEmpty; } get { return m_psEmpty; }
@@ -56,7 +55,7 @@ namespace ModernKeePassLib.Security
/// <summary> /// <summary>
/// A flag specifying whether the <c>ProtectedString</c> object /// A flag specifying whether the <c>ProtectedString</c> object
/// has turned on in-memory protection or not. /// has turned on memory protection or not.
/// </summary> /// </summary>
public bool IsProtected public bool IsProtected
{ {
@@ -80,10 +79,6 @@ namespace ModernKeePassLib.Security
{ {
get get
{ {
Debug.Assert(false, "not yet implemented");
return 0;
#if TODO
if(m_nCachedLength >= 0) return m_nCachedLength; if(m_nCachedLength >= 0) return m_nCachedLength;
ProtectedBinary pBin = m_pbUtf8; // Local ref for thread-safety ProtectedBinary pBin = m_pbUtf8; // Local ref for thread-safety
@@ -100,7 +95,6 @@ namespace ModernKeePassLib.Security
} }
return m_nCachedLength; return m_nCachedLength;
#endif
} }
} }
@@ -118,10 +112,9 @@ namespace ModernKeePassLib.Security
/// to the value supplied in the parameters. /// to the value supplied in the parameters.
/// </summary> /// </summary>
/// <param name="bEnableProtection">If this parameter is <c>true</c>, /// <param name="bEnableProtection">If this parameter is <c>true</c>,
/// the string will be protected in-memory (encrypted). If it /// the string will be protected in memory (encrypted). If it
/// is <c>false</c>, the string will be stored as plain-text.</param> /// is <c>false</c>, the string will be stored as plain-text.</param>
/// <param name="strValue">The initial string value. This /// <param name="strValue">The initial string value.</param>
/// parameter won't be modified.</param>
public ProtectedString(bool bEnableProtection, string strValue) public ProtectedString(bool bEnableProtection, string strValue)
{ {
Init(bEnableProtection, strValue); Init(bEnableProtection, strValue);
@@ -132,7 +125,7 @@ namespace ModernKeePassLib.Security
/// to the value supplied in the parameters (UTF-8 encoded string). /// to the value supplied in the parameters (UTF-8 encoded string).
/// </summary> /// </summary>
/// <param name="bEnableProtection">If this parameter is <c>true</c>, /// <param name="bEnableProtection">If this parameter is <c>true</c>,
/// the string will be protected in-memory (encrypted). If it /// the string will be protected in memory (encrypted). If it
/// is <c>false</c>, the string will be stored as plain-text.</param> /// is <c>false</c>, the string will be stored as plain-text.</param>
/// <param name="vUtf8Value">The initial string value, encoded as /// <param name="vUtf8Value">The initial string value, encoded as
/// UTF-8 byte array. This parameter won't be modified; the caller /// UTF-8 byte array. This parameter won't be modified; the caller
@@ -150,10 +143,9 @@ namespace ModernKeePassLib.Security
/// <param name="xbProtected"><c>XorredBuffer</c> object containing the /// <param name="xbProtected"><c>XorredBuffer</c> object containing the
/// string in UTF-8 representation. The UTF-8 string must not /// string in UTF-8 representation. The UTF-8 string must not
/// be <c>null</c>-terminated.</param> /// be <c>null</c>-terminated.</param>
/// <exception cref="System.ArgumentNullException">Thrown if the input
/// parameter is <c>null</c>.</exception>
public ProtectedString(bool bEnableProtection, XorredBuffer xbProtected) public ProtectedString(bool bEnableProtection, XorredBuffer xbProtected)
{ {
Debug.Assert(xbProtected != null);
if(xbProtected == null) throw new ArgumentNullException("xbProtected"); if(xbProtected == null) throw new ArgumentNullException("xbProtected");
byte[] pb = xbProtected.ReadPlainText(); byte[] pb = xbProtected.ReadPlainText();
@@ -196,7 +188,6 @@ namespace ModernKeePassLib.Security
if(m_strPlainText != null) return m_strPlainText; if(m_strPlainText != null) return m_strPlainText;
byte[] pb = ReadUtf8(); byte[] pb = ReadUtf8();
string str = ((pb.Length == 0) ? string.Empty : string str = ((pb.Length == 0) ? string.Empty :
StrUtil.Utf8.GetString(pb, 0, pb.Length)); StrUtil.Utf8.GetString(pb, 0, pb.Length));
// No need to clear pb // No need to clear pb
@@ -218,11 +209,7 @@ namespace ModernKeePassLib.Security
public byte[] ReadUtf8() public byte[] ReadUtf8()
{ {
ProtectedBinary pBin = m_pbUtf8; // Local ref for thread-safety ProtectedBinary pBin = m_pbUtf8; // Local ref for thread-safety
if(pBin != null) return pBin.ReadData();
if (pBin != null)
{
return pBin.ReadData();
}
return StrUtil.Utf8.GetBytes(m_strPlainText); return StrUtil.Utf8.GetBytes(m_strPlainText);
} }
@@ -233,8 +220,6 @@ namespace ModernKeePassLib.Security
/// </summary> /// </summary>
/// <param name="crsRandomSource">Random number source.</param> /// <param name="crsRandomSource">Random number source.</param>
/// <returns>Protected string.</returns> /// <returns>Protected string.</returns>
/// <exception cref="System.ArgumentNullException">Thrown if the input
/// parameter is <c>null</c>.</exception>
public byte[] ReadXorredString(CryptoRandomStream crsRandomSource) public byte[] ReadXorredString(CryptoRandomStream crsRandomSource)
{ {
Debug.Assert(crsRandomSource != null); if(crsRandomSource == null) throw new ArgumentNullException("crsRandomSource"); Debug.Assert(crsRandomSource != null); if(crsRandomSource == null) throw new ArgumentNullException("crsRandomSource");
@@ -243,7 +228,7 @@ namespace ModernKeePassLib.Security
uint uLen = (uint)pbData.Length; uint uLen = (uint)pbData.Length;
byte[] randomPad = crsRandomSource.GetRandomBytes(uLen); byte[] randomPad = crsRandomSource.GetRandomBytes(uLen);
Debug.Assert(randomPad.Length == uLen); Debug.Assert(randomPad.Length == pbData.Length);
for(uint i = 0; i < uLen; ++i) for(uint i = 0; i < uLen; ++i)
pbData[i] ^= randomPad[i]; pbData[i] ^= randomPad[i];
@@ -260,5 +245,100 @@ namespace ModernKeePassLib.Security
MemUtil.ZeroByteArray(pb); MemUtil.ZeroByteArray(pb);
return ps; return ps;
} }
public ProtectedString Insert(int iStart, string strInsert)
{
if(iStart < 0) throw new ArgumentOutOfRangeException("iStart");
if(strInsert == null) throw new ArgumentNullException("strInsert");
if(strInsert.Length == 0) return this;
// Only operate directly with strings when m_bIsProtected is
// false, not in the case of non-null m_strPlainText, because
// the operation creates a new sequence in memory
if(!m_bIsProtected)
return new ProtectedString(false, ReadString().Insert(
iStart, strInsert));
UTF8Encoding utf8 = StrUtil.Utf8;
byte[] pb = ReadUtf8();
char[] v = utf8.GetChars(pb);
char[] vNew;
try
{
if(iStart > v.Length)
throw new ArgumentOutOfRangeException("iStart");
char[] vIns = strInsert.ToCharArray();
vNew = new char[v.Length + vIns.Length];
Array.Copy(v, 0, vNew, 0, iStart);
Array.Copy(vIns, 0, vNew, iStart, vIns.Length);
Array.Copy(v, iStart, vNew, iStart + vIns.Length,
v.Length - iStart);
}
finally
{
Array.Clear(v, 0, v.Length);
MemUtil.ZeroByteArray(pb);
}
byte[] pbNew = utf8.GetBytes(vNew);
ProtectedString ps = new ProtectedString(m_bIsProtected, pbNew);
Debug.Assert(utf8.GetString(pbNew, 0, pbNew.Length) ==
ReadString().Insert(iStart, strInsert));
Array.Clear(vNew, 0, vNew.Length);
MemUtil.ZeroByteArray(pbNew);
return ps;
}
public ProtectedString Remove(int iStart, int nCount)
{
if(iStart < 0) throw new ArgumentOutOfRangeException("iStart");
if(nCount < 0) throw new ArgumentOutOfRangeException("nCount");
if(nCount == 0) return this;
// Only operate directly with strings when m_bIsProtected is
// false, not in the case of non-null m_strPlainText, because
// the operation creates a new sequence in memory
if(!m_bIsProtected)
return new ProtectedString(false, ReadString().Remove(
iStart, nCount));
UTF8Encoding utf8 = StrUtil.Utf8;
byte[] pb = ReadUtf8();
char[] v = utf8.GetChars(pb);
char[] vNew;
try
{
if((iStart + nCount) > v.Length)
throw new ArgumentException("iStart + nCount");
vNew = new char[v.Length - nCount];
Array.Copy(v, 0, vNew, 0, iStart);
Array.Copy(v, iStart + nCount, vNew, iStart, v.Length -
(iStart + nCount));
}
finally
{
Array.Clear(v, 0, v.Length);
MemUtil.ZeroByteArray(pb);
}
byte[] pbNew = utf8.GetBytes(vNew);
ProtectedString ps = new ProtectedString(m_bIsProtected, pbNew);
Debug.Assert(utf8.GetString(pbNew, 0, pbNew.Length) ==
ReadString().Remove(iStart, nCount));
Array.Clear(vNew, 0, vNew.Length);
MemUtil.ZeroByteArray(pbNew);
return ps;
}
} }
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -22,42 +22,74 @@ using System.Collections.Generic;
using System.Text; using System.Text;
using System.IO; using System.IO;
using ModernKeePassLib.Utility;
namespace ModernKeePassLib.Serialization namespace ModernKeePassLib.Serialization
{ {
public sealed class BinaryReaderEx : BinaryReader public sealed class BinaryReaderEx
{ {
private string m_strReadExcp = null; private Stream m_s;
// private Encoding m_enc; // See constructor
private string m_strReadExcp;
public string ReadExceptionText public string ReadExceptionText
{ {
get { return m_strReadExcp; } get { return m_strReadExcp; }
set { m_strReadExcp = value; } set { m_strReadExcp = value; }
} }
public BinaryReaderEx(Stream input, Encoding encoding, private Stream m_sCopyTo = null;
string strReadExceptionText) : /// <summary>
base(input, encoding) /// If this property is set to a non-null stream, all data that
/// is read from the input stream is automatically written to
/// the copy stream (before returning the read data).
/// </summary>
public Stream CopyDataTo
{ {
get { return m_sCopyTo; }
set { m_sCopyTo = value; }
}
public BinaryReaderEx(Stream input, Encoding encoding,
string strReadExceptionText)
{
if(input == null)
throw new ArgumentNullException("input");
m_s = input;
// m_enc = encoding; // Not used yet
m_strReadExcp = strReadExceptionText; m_strReadExcp = strReadExceptionText;
} }
public override byte[] ReadBytes(int count) public byte[] ReadBytes(int nCount)
{ {
/*try try
{*/ {
byte[] pb = base.ReadBytes(count); byte[] pb = MemUtil.Read(m_s, nCount);
if((pb == null) || (pb.Length != count)) if((pb == null) || (pb.Length != nCount))
{ {
if(m_strReadExcp != null) throw new IOException(m_strReadExcp); if(m_strReadExcp != null)
else throw new EndOfStreamException(); throw new IOException(m_strReadExcp);
else
throw new EndOfStreamException();
} }
if(m_sCopyTo != null)
m_sCopyTo.Write(pb, 0, pb.Length);
return pb; return pb;
/*} }
catch(Exception ex) catch(Exception)
{ {
if(m_strReadExcp != null) throw new IOException(m_strReadExcp); if(m_strReadExcp != null)
throw new IOException(m_strReadExcp);
else throw; else throw;
}*/ }
}
public byte ReadByte()
{
byte[] pb = ReadBytes(1);
return pb[0];
} }
} }
} }

View File

@@ -1,139 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using Windows.Storage.Streams;
namespace ModernKeePassLib.Serialization
{
// An adaptor function to provide a stream interface from an IBuffer.
class CryptoStream : Stream
{
private int m_blockSize = 16 ;
private byte[] m_decoded;
private IEnumerator<byte> m_enumerator = null;
public CryptoStream(Stream s, String strAlgName, bool bEncrypt, byte[] pbKey, byte[] pbIV)
{
IBuffer iv = CryptographicBuffer.CreateFromByteArray(pbIV);
SymmetricKeyAlgorithmProvider objAlg = SymmetricKeyAlgorithmProvider.OpenAlgorithm(strAlgName);
CryptographicKey key = objAlg.CreateSymmetricKey( CryptographicBuffer.CreateFromByteArray(pbKey) );
if (bEncrypt)
{
Debug.Assert(false, "Not implemented yet");
}
else
{
// For the time being, WinRT CryptographicEngine doesn't support stream decoding. Bummer.
// Copy the file to a memory buffer, then decode all at once.
byte[] block = new byte[s.Length]; // We are not at the beginning of the stream
// There is always less than s.Lenght bytes remaining to be read.
int readItemCount = s.Read(block, 0, (int) s.Length);
Array.Resize(ref block, readItemCount);
IBuffer input = CryptographicBuffer.CreateFromByteArray(block);
IBuffer decoded = null;
try
{
decoded = CryptographicEngine.Decrypt(key, input, iv);
} catch (System.Exception)
{
throw new Keys.InvalidCompositeKeyException();
}
CryptographicBuffer.CopyToByteArray(decoded, out m_decoded);
m_enumerator = m_decoded.AsEnumerable().GetEnumerator();
}
}
public override bool CanRead { get { return true; } }
public override bool CanSeek { get { return false; } }
public override bool CanTimeout { get { return false; } }
public override bool CanWrite { get { return false; } }
public override long Length
{
get
{
throw new System.NotSupportedException();
}
}
public override long Position {
get
{
throw new System.NotSupportedException();
}
set
{
throw new System.NotSupportedException();
}
}
public override void Flush()
{
Debug.Assert(false, "Not yet implemented");
}
public override int Read(byte[] buffer, int offset, int count)
{
// Exceptions:
// System.ArgumentException:
// The sum of offset and count is larger than the buffer length.
//
// System.ArgumentNullException:
// buffer is null.
//
// System.ArgumentOutOfRangeException:
// offset or count is negative.
//
// System.IO.IOException:
// An I/O error occurs.
//
// System.NotSupportedException:
// The stream does not support reading.
//
// System.ObjectDisposedException:
// Methods were called after the stream was closed.
if ((count <0) || (offset <0))
throw new System.ArgumentOutOfRangeException();
if (buffer == null)
throw new System.ArgumentNullException();
if (m_enumerator == null)
throw new System.ArgumentNullException();
for (int i = 0; i < count; i++)
{
if (!m_enumerator.MoveNext())
return i;
buffer[i + offset] = m_enumerator.Current;
}
return count;
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new System.NotSupportedException();
}
public override void SetLength(long value)
{
throw new System.NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new System.NotSupportedException();
}
}
}

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -21,7 +21,11 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.IO; using System.IO;
#if PCL
using System.Threading.Tasks;
#else
using System.Threading; using System.Threading;
#endif
using System.Diagnostics; using System.Diagnostics;
using ModernKeePassLib.Cryptography; using ModernKeePassLib.Cryptography;
@@ -41,28 +45,24 @@ namespace ModernKeePassLib.Serialization
public FileLockException(string strBaseFile, string strUser) public FileLockException(string strBaseFile, string strUser)
{ {
Debug.Assert(false, "Not yet implemented");
return;
#if TODO
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if(!string.IsNullOrEmpty(strBaseFile)) if(!string.IsNullOrEmpty(strBaseFile))
{ {
sb.Append(strBaseFile); sb.Append(strBaseFile);
sb.Append(MessageService.NewParagraph); sb.Append(Environment.NewLine + Environment.NewLine);
} }
sb.Append(KLRes.FileLockedWrite); sb.Append(KLRes.FileLockedWrite);
sb.Append(MessageService.NewLine); sb.Append(Environment.NewLine);
if(!string.IsNullOrEmpty(strUser)) sb.Append(strUser); if(!string.IsNullOrEmpty(strUser)) sb.Append(strUser);
else sb.Append("?"); else sb.Append("?");
sb.Append(MessageService.NewParagraph); sb.Append(Environment.NewLine + Environment.NewLine);
sb.Append(KLRes.TryAgainSecs); sb.Append(KLRes.TryAgainSecs);
m_strMsg = sb.ToString(); m_strMsg = sb.ToString();
#endif
} }
} }
@@ -124,9 +124,6 @@ namespace ModernKeePassLib.Serialization
public static LockFileInfo Load(IOConnectionInfo iocLockFile) public static LockFileInfo Load(IOConnectionInfo iocLockFile)
{ {
Debug.Assert(false, "not yet implemented");
return null;
#if TODO
Stream s = null; Stream s = null;
try try
{ {
@@ -134,7 +131,7 @@ namespace ModernKeePassLib.Serialization
if(s == null) return null; if(s == null) return null;
StreamReader sr = new StreamReader(s, StrUtil.Utf8); StreamReader sr = new StreamReader(s, StrUtil.Utf8);
string str = sr.ReadToEnd(); string str = sr.ReadToEnd();
sr.Close(); sr.Dispose();
if(str == null) { Debug.Assert(false); return null; } if(str == null) { Debug.Assert(false); return null; }
str = StrUtil.NormalizeNewLines(str, false); str = StrUtil.NormalizeNewLines(str, false);
@@ -146,18 +143,14 @@ namespace ModernKeePassLib.Serialization
} }
catch(FileNotFoundException) { } catch(FileNotFoundException) { }
catch(Exception) { Debug.Assert(false); } catch(Exception) { Debug.Assert(false); }
finally { if(s != null) s.Close(); } finally { if(s != null) s.Dispose(); }
return null; return null;
#endif
} }
// Throws on error // Throws on error
public static LockFileInfo Create(IOConnectionInfo iocLockFile) public static LockFileInfo Create(IOConnectionInfo iocLockFile)
{ {
Debug.Assert(false, "not yet implemented");
return null;
#if TODO
LockFileInfo lfi; LockFileInfo lfi;
Stream s = null; Stream s = null;
try try
@@ -165,7 +158,7 @@ namespace ModernKeePassLib.Serialization
byte[] pbID = CryptoRandom.Instance.GetRandomBytes(16); byte[] pbID = CryptoRandom.Instance.GetRandomBytes(16);
string strTime = TimeUtil.SerializeUtc(DateTime.Now); string strTime = TimeUtil.SerializeUtc(DateTime.Now);
#if !KeePassLibSD && TODO #if (!PCL && !KeePassLibSD && !KeePassRT)
lfi = new LockFileInfo(Convert.ToBase64String(pbID), strTime, lfi = new LockFileInfo(Convert.ToBase64String(pbID), strTime,
Environment.UserName, Environment.MachineName, Environment.UserName, Environment.MachineName,
Environment.UserDomainName); Environment.UserDomainName);
@@ -175,7 +168,7 @@ namespace ModernKeePassLib.Serialization
#endif #endif
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
#if !KeePassLibSD && TODO #if !KeePassLibSD
sb.AppendLine(LockFileHeader); sb.AppendLine(LockFileHeader);
sb.AppendLine(lfi.ID); sb.AppendLine(lfi.ID);
sb.AppendLine(strTime); sb.AppendLine(strTime);
@@ -197,18 +190,14 @@ namespace ModernKeePassLib.Serialization
if(s == null) throw new IOException(iocLockFile.GetDisplayName()); if(s == null) throw new IOException(iocLockFile.GetDisplayName());
s.Write(pbFile, 0, pbFile.Length); s.Write(pbFile, 0, pbFile.Length);
} }
finally { if(s != null) s.Close(); } finally { if(s != null) s.Dispose(); }
return lfi; return lfi;
#endif }
}
} }
public FileLock(IOConnectionInfo iocBaseFile) public FileLock(IOConnectionInfo iocBaseFile)
{ {
Debug.Assert(false, "not yet implemented");
return ;
#if TODO
if(iocBaseFile == null) throw new ArgumentNullException("strBaseFile"); if(iocBaseFile == null) throw new ArgumentNullException("strBaseFile");
m_iocLockFile = iocBaseFile.CloneDeep(); m_iocLockFile = iocBaseFile.CloneDeep();
@@ -223,7 +212,6 @@ namespace ModernKeePassLib.Serialization
} }
LockFileInfo.Create(m_iocLockFile); LockFileInfo.Create(m_iocLockFile);
#endif
} }
~FileLock() ~FileLock()
@@ -239,9 +227,6 @@ namespace ModernKeePassLib.Serialization
private void Dispose(bool bDisposing) private void Dispose(bool bDisposing)
{ {
Debug.Assert(false, "not yet implemented");
return ;
#if TODO
if(m_iocLockFile == null) return; if(m_iocLockFile == null) return;
bool bFileDeleted = false; bool bFileDeleted = false;
@@ -258,14 +243,18 @@ namespace ModernKeePassLib.Serialization
if(bFileDeleted) break; if(bFileDeleted) break;
#if PCL
if(bDisposing)
Task.Delay(50).Wait();
#else
if(bDisposing) Thread.Sleep(50); if(bDisposing) Thread.Sleep(50);
#endif
} }
if(bDisposing && !bFileDeleted) if(bDisposing && !bFileDeleted)
IOConnection.DeleteFile(m_iocLockFile); // Possibly with exception IOConnection.DeleteFile(m_iocLockFile); // Possibly with exception
m_iocLockFile = null; m_iocLockFile = null;
#endif
} }
// private bool OwnLockFile() // private bool OwnLockFile()

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -22,13 +22,8 @@ using System.Collections.Generic;
using System.Text; using System.Text;
using System.IO; using System.IO;
using System.Diagnostics; using System.Diagnostics;
using System.Threading.Tasks;
// Bert TODO: For now, remove the accesscontrol from this class. #if (!PCL && !KeePassLibSD && !KeePassRT)
// In WinRT, the security of file has changed, and something could potentially be done
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364399%28v=vs.85%29.aspx
#if !KeePassLibSD && TODO
using System.Security.AccessControl; using System.Security.AccessControl;
#endif #endif
@@ -63,6 +58,16 @@ namespace ModernKeePassLib.Serialization
m_bTransacted = bTransacted; m_bTransacted = bTransacted;
m_iocBase = iocBaseFile.CloneDeep(); m_iocBase = iocBaseFile.CloneDeep();
// ModernKeePassLib is currently targeting .NET 4.5
#if !PCL
// Prevent transactions for FTP URLs under .NET 4.0 in order to
// avoid/workaround .NET bug 621450:
// https://connect.microsoft.com/VisualStudio/feedback/details/621450/problem-renaming-file-on-ftp-server-using-ftpwebrequest-in-net-framework-4-0-vs2010-only
if(m_iocBase.Path.StartsWith("ftp:", StrUtil.CaseIgnoreCmp) &&
(Environment.Version.Major >= 4) && !NativeLib.IsUnix())
m_bTransacted = false;
#endif
if(m_bTransacted) if(m_bTransacted)
{ {
m_iocTemp = m_iocBase.CloneDeep(); m_iocTemp = m_iocBase.CloneDeep();
@@ -71,7 +76,7 @@ namespace ModernKeePassLib.Serialization
else m_iocTemp = m_iocBase; else m_iocTemp = m_iocBase;
} }
public async Task<Stream> OpenWrite() public Stream OpenWrite()
{ {
if(!m_bTransacted) m_bMadeUnhidden = UrlUtil.UnhideFile(m_iocTemp.Path); if(!m_bTransacted) m_bMadeUnhidden = UrlUtil.UnhideFile(m_iocTemp.Path);
else // m_bTransacted else // m_bTransacted
@@ -80,7 +85,7 @@ namespace ModernKeePassLib.Serialization
catch(Exception) { } catch(Exception) { }
} }
return await IOConnection.OpenWrite(m_iocTemp); return IOConnection.OpenWrite(m_iocTemp);
} }
public void CommitWrite() public void CommitWrite()
@@ -96,14 +101,14 @@ namespace ModernKeePassLib.Serialization
{ {
bool bMadeUnhidden = UrlUtil.UnhideFile(m_iocBase.Path); bool bMadeUnhidden = UrlUtil.UnhideFile(m_iocBase.Path);
#if !KeePassLibSD && TODO #if (!PCL && !KeePassLibSD && !KeePassRT)
FileSecurity bkSecurity = null; FileSecurity bkSecurity = null;
bool bEfsEncrypted = false; bool bEfsEncrypted = false;
#endif #endif
if(IOConnection.FileExists(m_iocBase)) if(IOConnection.FileExists(m_iocBase))
{ {
#if !KeePassLibSD && TODO #if (!PCL && !KeePassLibSD && !KeePassRT)
if(m_iocBase.IsLocalFile()) if(m_iocBase.IsLocalFile())
{ {
try try
@@ -125,7 +130,7 @@ namespace ModernKeePassLib.Serialization
IOConnection.RenameFile(m_iocTemp, m_iocBase); IOConnection.RenameFile(m_iocTemp, m_iocBase);
#if !KeePassLibSD && TODO #if (!PCL && !KeePassLibSD && !KeePassRT)
if(m_iocBase.IsLocalFile()) if(m_iocBase.IsLocalFile())
{ {
try try

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -19,19 +19,24 @@
using System; using System;
using System.IO; using System.IO;
#if PCL
using System.Linq;
#else
using System.Security.Cryptography;
#endif
using System.Diagnostics;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text; using System.Text;
using Windows.Security.Cryptography.Core;
using ModernKeePassLib.Native;
using ModernKeePassLib.Utility; using ModernKeePassLib.Utility;
using ModernKeePassLib.Cryptography;
#if KeePassLibSD #if KeePassLibSD
using ModernKeePassLibSD; using KeePassLibSD;
#endif #endif
namespace ModernKeePassLib.Serialization namespace ModernKeePassLib.Serialization
{ {
public sealed class HashedBlockStream : Stream public sealed class HashedBlockStream : Stream
{ {
private const int m_nDefaultBufferSize = 1024 * 1024; // 1 MB private const int m_nDefaultBufferSize = 1024 * 1024; // 1 MB
@@ -93,12 +98,13 @@ namespace ModernKeePassLib.Serialization
private void Initialize(Stream sBaseStream, bool bWriting, int nBufferSize, private void Initialize(Stream sBaseStream, bool bWriting, int nBufferSize,
bool bVerify) bool bVerify)
{ {
if(sBaseStream == null) throw new ArgumentNullException("sBaseStream"); if (sBaseStream == null) throw new ArgumentNullException(nameof(sBaseStream));
if(nBufferSize < 0) throw new ArgumentOutOfRangeException("nBufferSize"); m_sBaseStream = sBaseStream;
if (nBufferSize < 0)
throw new ArgumentOutOfRangeException(nameof(nBufferSize));
if(nBufferSize == 0) nBufferSize = m_nDefaultBufferSize; if(nBufferSize == 0)
nBufferSize = m_nDefaultBufferSize;
m_sBaseStream = sBaseStream;
m_bWriting = bWriting; m_bWriting = bWriting;
m_bVerify = bVerify; m_bVerify = bVerify;
@@ -128,14 +134,20 @@ namespace ModernKeePassLib.Serialization
if(m_bWriting) m_bwOutput.Flush(); if(m_bWriting) m_bwOutput.Flush();
} }
#if TODO #if PCL || KeePassRT
protected override void Dispose(bool disposing)
{
if(!disposing) return;
#else
public override void Close() public override void Close()
{ {
#endif
if(m_sBaseStream != null) if(m_sBaseStream != null)
{ {
if(m_bWriting == false) // Reading mode if(m_bWriting == false) // Reading mode
{ {
m_brInput.Close(); try { m_brInput.Dispose(); } catch { }
m_brInput = null; m_brInput = null;
} }
else // Writing mode else // Writing mode
@@ -149,15 +161,14 @@ namespace ModernKeePassLib.Serialization
} }
Flush(); Flush();
m_bwOutput.Close(); m_bwOutput.Dispose();
m_bwOutput = null; m_bwOutput = null;
} }
m_sBaseStream.Close(); try { m_sBaseStream.Dispose(); } catch { }
m_sBaseStream = null; m_sBaseStream = null;
} }
} }
#endif
public override long Seek(long lOffset, SeekOrigin soOrigin) public override long Seek(long lOffset, SeekOrigin soOrigin)
{ {
@@ -210,11 +221,11 @@ namespace ModernKeePassLib.Serialization
throw new InvalidDataException(); throw new InvalidDataException();
int nBufferSize = 0; int nBufferSize = 0;
try { nBufferSize = m_brInput.ReadInt32(); } /*try {*/ nBufferSize = m_brInput.ReadInt32(); /*}
catch(NullReferenceException) // Mono bug workaround (LaunchPad 783268) catch(NullReferenceException) // Mono bug workaround (LaunchPad 783268)
{ {
if(!NativeLib.IsUnix()) throw; if(!NativeLib.IsUnix()) throw;
} }*/
if(nBufferSize < 0) if(nBufferSize < 0)
throw new InvalidDataException(); throw new InvalidDataException();
@@ -238,7 +249,13 @@ namespace ModernKeePassLib.Serialization
if(m_bVerify) if(m_bVerify)
{ {
byte[] pbComputedHash = SHA256Managed.Instance.ComputeHash(m_pbBuffer); #if PCL
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
var pbComputedHash = sha256.HashData(m_pbBuffer.AsBuffer()).ToArray();
#else
SHA256Managed sha256 = new SHA256Managed();
byte[] pbComputedHash = sha256.ComputeHash(m_pbBuffer);
#endif
if((pbComputedHash == null) || (pbComputedHash.Length != 32)) if((pbComputedHash == null) || (pbComputedHash.Length != 32))
throw new InvalidOperationException(); throw new InvalidOperationException();
@@ -247,8 +264,7 @@ namespace ModernKeePassLib.Serialization
if(pbStoredHash[iHashPos] != pbComputedHash[iHashPos]) if(pbStoredHash[iHashPos] != pbComputedHash[iHashPos])
throw new InvalidDataException(); throw new InvalidDataException();
} }
} }
return true; return true;
} }
@@ -275,14 +291,16 @@ namespace ModernKeePassLib.Serialization
private void WriteHashedBlock() private void WriteHashedBlock()
{ {
Debug.Assert(false, "not yet implemented");
return ;
#if TODO
m_bwOutput.Write(m_uBufferIndex); m_bwOutput.Write(m_uBufferIndex);
++m_uBufferIndex; ++m_uBufferIndex;
if(m_nBufferPos > 0) if(m_nBufferPos > 0)
{ {
#if PCL
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
var pbHash = sha256.HashData(m_pbBuffer.Where((x, i) => i < m_nBufferPos).ToArray().AsBuffer()).ToArray();
#else
SHA256Managed sha256 = new SHA256Managed(); SHA256Managed sha256 = new SHA256Managed();
#if !KeePassLibSD #if !KeePassLibSD
@@ -297,6 +315,8 @@ namespace ModernKeePassLib.Serialization
Array.Copy(m_pbBuffer, 0, pbData, 0, m_nBufferPos); Array.Copy(m_pbBuffer, 0, pbData, 0, m_nBufferPos);
pbHash = sha256.ComputeHash(pbData); pbHash = sha256.ComputeHash(pbData);
} }
#endif
#endif #endif
m_bwOutput.Write(pbHash); m_bwOutput.Write(pbHash);
@@ -315,7 +335,6 @@ namespace ModernKeePassLib.Serialization
m_bwOutput.Write(m_pbBuffer, 0, m_nBufferPos); m_bwOutput.Write(m_pbBuffer, 0, m_nBufferPos);
m_nBufferPos = 0; m_nBufferPos = 0;
#endif
} }
} }
} }

View File

@@ -1,12 +1,13 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@@ -18,27 +19,32 @@
*/ */
using System; using System;
using System.Net; using System.Collections.Generic;
using System.Net.Http; using System.Text;
using System.Threading.Tasks;
using System.IO; using System.IO;
using System.Net;
using System.Reflection;
using System.Diagnostics;
using Windows.Storage.Streams; #if (!PCL && !KeePassLibSD && !KeePassRT)
using Windows.Storage;
// BERT TODO: For the time being, the web functionality is not available for WinRT
#if !KeePassLibSD && TODO
using System.Net.Cache; using System.Net.Cache;
using System.Net.Security; using System.Net.Security;
#endif #endif
#if !PCL && !KeePassRT
using System.Security.Cryptography.X509Certificates;
#endif
#if PCL
using Windows.Storage;
#endif
using ModernKeePassLib.Utility; using ModernKeePassLib.Utility;
namespace ModernKeePassLib.Serialization namespace ModernKeePassLib.Serialization
{ {
#if !KeePassLibSD && false #if (!PCL && !KeePassLibSD && !KeePassRT)
public sealed class IOWebClient : HttpClient internal sealed class IOWebClient : WebClient
{ {
protected override WebRequest GetWebRequest(Uri address) protected override WebRequest GetWebRequest(Uri address)
{ {
@@ -49,14 +55,192 @@ namespace ModernKeePassLib.Serialization
} }
#endif #endif
public class IOConnection #if !PCL
internal abstract class WrapperStream : Stream
{ {
#if !KeePassLibSD && TODO private readonly Stream m_s;
protected Stream BaseStream
{
get { return m_s; }
}
public override bool CanRead
{
get { return m_s.CanRead; }
}
public override bool CanSeek
{
get { return m_s.CanSeek; }
}
public override bool CanTimeout
{
get { return m_s.CanTimeout; }
}
public override bool CanWrite
{
get { return m_s.CanWrite; }
}
public override long Length
{
get { return m_s.Length; }
}
public override long Position
{
get { return m_s.Position; }
set { m_s.Position = value; }
}
public override int ReadTimeout
{
get { return m_s.ReadTimeout; }
set { m_s.ReadTimeout = value; }
}
public override int WriteTimeout
{
get { return m_s.WriteTimeout; }
set { m_s.WriteTimeout = value; }
}
public WrapperStream(Stream sBase) : base()
{
if(sBase == null) throw new ArgumentNullException("sBase");
m_s = sBase;
}
public override IAsyncResult BeginRead(byte[] buffer, int offset,
int count, AsyncCallback callback, object state)
{
return m_s.BeginRead(buffer, offset, count, callback, state);
}
public override IAsyncResult BeginWrite(byte[] buffer, int offset,
int count, AsyncCallback callback, object state)
{
return BeginWrite(buffer, offset, count, callback, state);
}
public override void Close()
{
m_s.Close();
}
public override int EndRead(IAsyncResult asyncResult)
{
return m_s.EndRead(asyncResult);
}
public override void EndWrite(IAsyncResult asyncResult)
{
m_s.EndWrite(asyncResult);
}
public override void Flush()
{
m_s.Flush();
}
public override int Read(byte[] buffer, int offset, int count)
{
return m_s.Read(buffer, offset, count);
}
public override int ReadByte()
{
return m_s.ReadByte();
}
public override long Seek(long offset, SeekOrigin origin)
{
return m_s.Seek(offset, origin);
}
public override void SetLength(long value)
{
m_s.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
m_s.Write(buffer, offset, count);
}
public override void WriteByte(byte value)
{
m_s.WriteByte(value);
}
}
internal sealed class IocStream : WrapperStream
{
private readonly bool m_bWrite; // Initially opened for writing
public IocStream(Stream sBase) : base(sBase)
{
m_bWrite = sBase.CanWrite;
}
public override void Close()
{
base.Close();
if(MonoWorkarounds.IsRequired(10163) && m_bWrite)
{
try
{
Stream s = this.BaseStream;
Type t = s.GetType();
if(t.Name == "WebConnectionStream")
{
PropertyInfo pi = t.GetProperty("Request",
BindingFlags.Instance | BindingFlags.NonPublic);
if(pi != null)
{
WebRequest wr = (pi.GetValue(s, null) as WebRequest);
if(wr != null)
IOConnection.DisposeResponse(wr.GetResponse(), false);
else { Debug.Assert(false); }
}
else { Debug.Assert(false); }
}
}
catch(Exception) { Debug.Assert(false); }
}
}
public static Stream WrapIfRequired(Stream s)
{
if(s == null) { Debug.Assert(false); return null; }
if(MonoWorkarounds.IsRequired(10163) && s.CanWrite)
return new IocStream(s);
return s;
}
}
#endif
public static class IOConnection
{
#if (!PCL && !KeePassLibSD && !KeePassRT)
private static ProxyServerType m_pstProxyType = ProxyServerType.System; private static ProxyServerType m_pstProxyType = ProxyServerType.System;
private static string m_strProxyAddr = string.Empty; private static string m_strProxyAddr = string.Empty;
private static string m_strProxyPort = string.Empty; private static string m_strProxyPort = string.Empty;
private static string m_strProxyUserName = string.Empty; private static string m_strProxyUserName = string.Empty;
private static string m_strProxyPassword = string.Empty; private static string m_strProxyPassword = string.Empty;
private static bool m_bSslCertsAcceptInvalid = false;
internal static bool SslCertsAcceptInvalid
{
// get { return m_bSslCertsAcceptInvalid; }
set { m_bSslCertsAcceptInvalid = value; }
}
#endif #endif
// Web request methods // Web request methods
@@ -66,16 +250,18 @@ namespace ModernKeePassLib.Serialization
// Web request headers // Web request headers
public const string WrhMoveFileTo = "MoveFileTo"; public const string WrhMoveFileTo = "MoveFileTo";
#if !KeePassLibSD && TODO public static event EventHandler<IOAccessEventArgs> IOAccessPre;
#if (!PCL && !KeePassLibSD && !KeePassRT)
// Allow self-signed certificates, expired certificates, etc. // Allow self-signed certificates, expired certificates, etc.
private static bool ValidateServerCertificate(object sender, private static bool AcceptCertificate(object sender,
X509Certificate certificate, X509Chain chain, X509Certificate certificate, X509Chain chain,
SslPolicyErrors sslPolicyErrors) SslPolicyErrors sslPolicyErrors)
{ {
return true; return true;
} }
public static void SetProxy(ProxyServerType pst, string strAddr, internal static void SetProxy(ProxyServerType pst, string strAddr,
string strPort, string strUserName, string strPassword) string strPort, string strUserName, string strPassword)
{ {
m_pstProxyType = pst; m_pstProxyType = pst;
@@ -185,12 +371,27 @@ namespace ModernKeePassLib.Serialization
private static void PrepareWebAccess() private static void PrepareWebAccess()
{ {
ServicePointManager.ServerCertificateValidationCallback = if(m_bSslCertsAcceptInvalid)
ValidateServerCertificate; ServicePointManager.ServerCertificateValidationCallback =
IOConnection.AcceptCertificate;
else
ServicePointManager.ServerCertificateValidationCallback = null;
} }
private static IOWebClient CreateWebClient(IOConnectionInfo ioc)
{
PrepareWebAccess();
IOWebClient wc = new IOWebClient();
ConfigureWebClient(wc);
if((ioc.UserName.Length > 0) || (ioc.Password.Length > 0))
wc.Credentials = new NetworkCredential(ioc.UserName, ioc.Password);
else if(NativeLib.IsUnix()) // Mono requires credentials
wc.Credentials = new NetworkCredential("anonymous", string.Empty);
return wc;
}
private static WebRequest CreateWebRequest(IOConnectionInfo ioc) private static WebRequest CreateWebRequest(IOConnectionInfo ioc)
{ {
@@ -206,122 +407,124 @@ namespace ModernKeePassLib.Serialization
return req; return req;
} }
#endif
private async Task<Stream> OpenReadHttp(IOConnectionInfo ioc) public static Stream OpenRead(IOConnectionInfo ioc)
{
// TODO: Configure the httpClient
// PrepareWebAccess();
// ConfigureWebClient(wc);
HttpClient hc = new HttpClient();
HttpResponseMessage response = await hc.GetAsync(ioc.Path);
response.EnsureSuccessStatusCode();
// Read content into buffer
// Not the most efficient thing to do,
// but simplifies our life by allowing to use stream.length later on.
await response.Content.LoadIntoBufferAsync();
return await response.Content.ReadAsStreamAsync();
#if false
if((ioc.UserName.Length > 0) || (ioc.Password.Length > 0))
wc.Credentials = new NetworkCredential(ioc.UserName, ioc.Password);
else if(NativeLib.IsUnix()) // Mono requires credentials
wc.Credentials = new NetworkCredential("anonymous", string.Empty);
#endif
}
public async Task<Stream> OpenRead(IOConnectionInfo ioc)
{ {
RaiseIOAccessPreEvent(ioc, IOAccessType.Read);
if(StrUtil.IsDataUri(ioc.Path)) if(StrUtil.IsDataUri(ioc.Path))
{ {
byte[] pbData = StrUtil.DataUriToData(ioc.Path); byte[] pbData = StrUtil.DataUriToData(ioc.Path);
if(pbData != null) return new MemoryStream(pbData, false); if(pbData != null) return new MemoryStream(pbData, false);
} }
if(ioc.IsLocalFile()) return await OpenReadLocal(ioc); if(ioc.IsLocalFile()) return OpenReadLocal(ioc);
return IocStream.WrapIfRequired(CreateWebClient(ioc).OpenRead(
return await OpenReadHttp(ioc); new Uri(ioc.Path)));
} }
#else
public static Stream OpenRead(IOConnectionInfo ioc)
private async Task<Stream> OpenReadLocal(IOConnectionInfo ioc)
{ {
try RaiseIOAccessPreEvent(ioc, IOAccessType.Read);
{
IRandomAccessStream stream = await ioc.StorageFile.OpenAsync(FileAccessMode.Read); return OpenReadLocal(ioc);
return stream.AsStream(); }
} #endif
catch (Exception ex)
{ private static Stream OpenReadLocal(IOConnectionInfo ioc)
Debug.Assert(false, ex.Message); {
return null; #if PCL
} /*var file = FileSystem.Current.GetFileFromPathAsync(ioc.Path).Result;
return file.OpenAsync(PCLStorage.FileAccess.Read).Result;*/
return ioc.StorageFile.OpenAsync(FileAccessMode.Read).GetResults().AsStream();
#else
return new FileStream(ioc.Path, FileMode.Open, FileAccess.Read,
FileShare.Read);
#endif
} }
#if !KeePassLibSD && TODO #if (!PCL && !KeePassLibSD && !KeePassRT)
public static Stream OpenWrite(IOConnectionInfo ioc) public static Stream OpenWrite(IOConnectionInfo ioc)
{ {
if(ioc == null) { Debug.Assert(false); return null; } if(ioc == null) { Debug.Assert(false); return null; }
RaiseIOAccessPreEvent(ioc, IOAccessType.Write);
if(ioc.IsLocalFile()) return OpenWriteLocal(ioc); if(ioc.IsLocalFile()) return OpenWriteLocal(ioc);
Uri uri = new Uri(ioc.Path); Uri uri = new Uri(ioc.Path);
Stream s;
// Mono does not set HttpWebRequest.Method to POST for writes, // Mono does not set HttpWebRequest.Method to POST for writes,
// so one needs to set the method to PUT explicitly // so one needs to set the method to PUT explicitly
if(NativeLib.IsUnix() && (uri.Scheme.Equals(Uri.UriSchemeHttp, if(NativeLib.IsUnix() && (uri.Scheme.Equals(Uri.UriSchemeHttp,
StrUtil.CaseIgnoreCmp) || uri.Scheme.Equals(Uri.UriSchemeHttps, StrUtil.CaseIgnoreCmp) || uri.Scheme.Equals(Uri.UriSchemeHttps,
StrUtil.CaseIgnoreCmp))) StrUtil.CaseIgnoreCmp)))
return CreateWebClient(ioc).OpenWrite(uri, WebRequestMethods.Http.Put); s = CreateWebClient(ioc).OpenWrite(uri, WebRequestMethods.Http.Put);
else s = CreateWebClient(ioc).OpenWrite(uri);
return CreateWebClient(ioc).OpenWrite(uri); return IocStream.WrapIfRequired(s);
} }
#else #else
public static async Task<Stream> OpenWrite(IOConnectionInfo ioc) public static Stream OpenWrite(IOConnectionInfo ioc)
{ {
return await OpenWriteLocal(ioc); RaiseIOAccessPreEvent(ioc, IOAccessType.Write);
return OpenWriteLocal(ioc);
} }
#endif #endif
private static async Task<Stream> OpenWriteLocal(IOConnectionInfo ioc) private static Stream OpenWriteLocal(IOConnectionInfo ioc)
{ {
try #if PCL
{ return ioc.StorageFile.OpenAsync(FileAccessMode.ReadWrite).GetResults().AsStream();
IRandomAccessStream stream = await ioc.StorageFile.OpenAsync(FileAccessMode.ReadWrite); /*var file = FileSystem.Current.GetFileFromPathAsync(ioc.Path).Result;
return stream.AsStream(); return file.OpenAsync(FileAccess.ReadAndWrite).Result;*/
} #else
catch (Exception ex) return new FileStream(ioc.Path, FileMode.Create, FileAccess.Write,
{ FileShare.None);
Debug.Assert(false, ex.Message); #endif
return null; }
}
}
public static bool FileExists(IOConnectionInfo ioc) public static bool FileExists(IOConnectionInfo ioc)
{ {
//return FileExists(ioc, false); return FileExists(ioc, false);
return true;
} }
/*public static bool FileExists(IOConnectionInfo ioc, bool bThrowErrors) public static bool FileExists(IOConnectionInfo ioc, bool bThrowErrors)
{ {
if(ioc == null) { Debug.Assert(false); return false; } if(ioc == null) { Debug.Assert(false); return false; }
if(ioc.IsLocalFile()) return ioc.StorageFile.IsAvailable; RaiseIOAccessPreEvent(ioc, IOAccessType.Exists);
#if PCL
if(ioc.IsLocalFile())
return ioc.StorageFile.IsAvailable;
#else
if(ioc.IsLocalFile()) return File.Exists(ioc.Path);
#endif
#if (!PCL && !KeePassLibSD && !KeePassRT)
if(ioc.Path.StartsWith("ftp://", StrUtil.CaseIgnoreCmp))
{
bool b = SendCommand(ioc, WebRequestMethods.Ftp.GetDateTimestamp);
if(!b && bThrowErrors) throw new InvalidOperationException();
return b;
}
#endif
try try
{ {
Stream s = OpenRead(ioc); Stream s = OpenRead(ioc);
if(s == null) throw new FileNotFoundException(); if(s == null) throw new FileNotFoundException();
// For FTP clients we called RETR to get the file, but we never try { s.ReadByte(); }
// followed-up and downloaded the file; close may produce a catch(Exception) { }
// 550 error -- that's okay
try { s.Close(); } // We didn't download the file completely; close may throw
// an exception -- that's okay
try { s.Dispose(); }
catch(Exception) { } catch(Exception) { }
} }
catch(Exception) catch(Exception)
@@ -331,19 +534,29 @@ namespace ModernKeePassLib.Serialization
} }
return true; return true;
}*/ }
public static async void DeleteFile(IOConnectionInfo ioc) public static void DeleteFile(IOConnectionInfo ioc)
{ {
if(ioc.IsLocalFile()) { await ioc.StorageFile.DeleteAsync(StorageDeleteOption.Default); RaiseIOAccessPreEvent(ioc, IOAccessType.Delete);
}
#if !KeePassLibSD && TODO #if PCL
if(ioc.IsLocalFile()) {
/*var file = FileSystem.Current.GetFileFromPathAsync(ioc.Path).Result;
file.DeleteAsync().RunSynchronously();*/
ioc.StorageFile.DeleteAsync(StorageDeleteOption.Default).GetResults();
}
#else
if(ioc.IsLocalFile()) { File.Delete(ioc.Path); return; }
#endif
#if (!PCL && !KeePassLibSD && !KeePassRT)
WebRequest req = CreateWebRequest(ioc); WebRequest req = CreateWebRequest(ioc);
if(req != null) if(req != null)
{ {
if(req is HttpWebRequest) req.Method = "DELETE"; if(req is HttpWebRequest) req.Method = "DELETE";
else if(req is FtpWebRequest) req.Method = WebRequestMethods.Ftp.DeleteFile; else if(req is FtpWebRequest)
req.Method = WebRequestMethods.Ftp.DeleteFile;
else if(req is FileWebRequest) else if(req is FileWebRequest)
{ {
File.Delete(UrlUtil.FileUrlToPath(ioc.Path)); File.Delete(UrlUtil.FileUrlToPath(ioc.Path));
@@ -365,11 +578,22 @@ namespace ModernKeePassLib.Serialization
/// </summary> /// </summary>
/// <param name="iocFrom">Source file path.</param> /// <param name="iocFrom">Source file path.</param>
/// <param name="iocTo">Target file path.</param> /// <param name="iocTo">Target file path.</param>
public static async void RenameFile(IOConnectionInfo iocFrom, IOConnectionInfo iocTo) public static void RenameFile(IOConnectionInfo iocFrom, IOConnectionInfo iocTo)
{ {
if(iocFrom.IsLocalFile()) { await iocTo.StorageFile.RenameAsync(iocTo.Path, NameCollisionOption.GenerateUniqueName); } RaiseIOAccessPreEvent(iocFrom, iocTo, IOAccessType.Move);
#if !KeePassLibSD && TODO #if PCL
if(iocFrom.IsLocalFile()) {
/*var file = FileSystem.Current.GetFileFromPathAsync(iocFrom.Path).Result;
file.MoveAsync(iocTo.Path).RunSynchronously();*/
iocFrom.StorageFile.RenameAsync(iocTo.Path).GetResults();
return;
}
#else
if(iocFrom.IsLocalFile()) { File.Move(iocFrom.Path, iocTo.Path); return; }
#endif
#if (!PCL && !KeePassLibSD && !KeePassRT)
WebRequest req = CreateWebRequest(iocFrom); WebRequest req = CreateWebRequest(iocFrom);
if(req != null) if(req != null)
{ {
@@ -381,7 +605,13 @@ namespace ModernKeePassLib.Serialization
else if(req is FtpWebRequest) else if(req is FtpWebRequest)
{ {
req.Method = WebRequestMethods.Ftp.Rename; req.Method = WebRequestMethods.Ftp.Rename;
((FtpWebRequest)req).RenameTo = UrlUtil.GetFileName(iocTo.Path); string strTo = UrlUtil.GetFileName(iocTo.Path);
// We're affected by .NET bug 621450:
// https://connect.microsoft.com/VisualStudio/feedback/details/621450/problem-renaming-file-on-ftp-server-using-ftpwebrequest-in-net-framework-4-0-vs2010-only
// Prepending "./", "%2E/" or "Dummy/../" doesn't work.
((FtpWebRequest)req).RenameTo = strTo;
} }
else if(req is FileWebRequest) else if(req is FileWebRequest)
{ {
@@ -412,11 +642,23 @@ namespace ModernKeePassLib.Serialization
// DeleteFile(iocFrom); // DeleteFile(iocFrom);
} }
private static void DisposeResponse(WebResponse wr, bool bGetStream) #if (!PCL && !KeePassLibSD && !KeePassRT)
private static bool SendCommand(IOConnectionInfo ioc, string strMethod)
{
try
{
WebRequest req = CreateWebRequest(ioc);
req.Method = strMethod;
DisposeResponse(req.GetResponse(), true);
}
catch(Exception) { return false; }
return true;
}
#endif
internal static void DisposeResponse(WebResponse wr, bool bGetStream)
{ {
Debug.Assert(false, "Not implemented yet");
return;
#if TODO
if(wr == null) return; if(wr == null) return;
try try
@@ -424,12 +666,12 @@ namespace ModernKeePassLib.Serialization
if(bGetStream) if(bGetStream)
{ {
Stream s = wr.GetResponseStream(); Stream s = wr.GetResponseStream();
if(s != null) s.Close(); if(s != null) s.Dispose();
} }
} }
catch(Exception) { Debug.Assert(false); } catch(Exception) { Debug.Assert(false); }
try { wr.Close(); } try { wr.Dispose(); }
catch(Exception) { Debug.Assert(false); } catch(Exception) { Debug.Assert(false); }
} }
@@ -450,12 +692,30 @@ namespace ModernKeePassLib.Serialization
catch(Exception) { } catch(Exception) { }
finally finally
{ {
if(sIn != null) sIn.Close(); if(sIn != null) sIn.Dispose();
if(ms != null) ms.Close(); if(ms != null) ms.Dispose();
} }
return null; return null;
#endif }
}
private static void RaiseIOAccessPreEvent(IOConnectionInfo ioc, IOAccessType t)
{
RaiseIOAccessPreEvent(ioc, null, t);
}
private static void RaiseIOAccessPreEvent(IOConnectionInfo ioc,
IOConnectionInfo ioc2, IOAccessType t)
{
if(ioc == null) { Debug.Assert(false); return; }
// ioc2 may be null
if(IOConnection.IOAccessPre != null)
{
IOConnectionInfo ioc2Lcl = ((ioc2 != null) ? ioc2.CloneDeep() : null);
IOAccessEventArgs e = new IOAccessEventArgs(ioc.CloneDeep(), ioc2Lcl, t);
IOConnection.IOAccessPre(null, e);
}
}
} }
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -23,11 +23,15 @@ using System.Text;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.ComponentModel; using System.ComponentModel;
using System.Xml.Serialization;
using System.Diagnostics; using System.Diagnostics;
#if PCL
using Windows.Storage;
#endif
using ModernKeePassLib.Interfaces; using ModernKeePassLib.Interfaces;
using ModernKeePassLib.Utility; using ModernKeePassLib.Utility;
using Windows.Storage;
namespace ModernKeePassLib.Serialization namespace ModernKeePassLib.Serialization
{ {
@@ -65,7 +69,7 @@ namespace ModernKeePassLib.Serialization
{ {
// private IOFileFormatHint m_ioHint = IOFileFormatHint.None; // private IOFileFormatHint m_ioHint = IOFileFormatHint.None;
public StorageFile StorageFile { get; set; } public StorageFile StorageFile { get; set; }
private string m_strUrl = string.Empty; private string m_strUrl = string.Empty;
public string Path public string Path
@@ -122,6 +126,14 @@ namespace ModernKeePassLib.Serialization
set { m_ioCredSaveMode = value; } set { m_ioCredSaveMode = value; }
} }
private bool m_bComplete = false;
[XmlIgnore]
public bool IsComplete // Credentials etc. fully specified
{
get { return m_bComplete; }
set { m_bComplete = value; }
}
/* public IOFileFormatHint FileFormatHint /* public IOFileFormatHint FileFormatHint
{ {
get { return m_ioHint; } get { return m_ioHint; }
@@ -133,11 +145,17 @@ namespace ModernKeePassLib.Serialization
return (IOConnectionInfo)this.MemberwiseClone(); return (IOConnectionInfo)this.MemberwiseClone();
} }
#if DEBUG // For debugger display only
public override string ToString()
{
return GetDisplayName();
}
#endif
/* /*
/// <summary> /// <summary>
/// Serialize the current connection info to a string. Credentials /// Serialize the current connection info to a string. Credentials
/// are only serialized if the <c>SaveCredentials</c> property /// are serialized based on the <c>CredSaveMode</c> property.
/// is <c>true</c>.
/// </summary> /// </summary>
/// <param name="iocToCompile">Input object to be serialized.</param> /// <param name="iocToCompile">Input object to be serialized.</param>
/// <returns>Serialized object as string.</returns> /// <returns>Serialized object as string.</returns>
@@ -149,31 +167,9 @@ namespace ModernKeePassLib.Serialization
string strUrl = iocToCompile.Path; string strUrl = iocToCompile.Path;
string strUser = TransformUnreadable(iocToCompile.UserName, true); string strUser = TransformUnreadable(iocToCompile.UserName, true);
string strPassword = TransformUnreadable(iocToCompile.Password, true); string strPassword = TransformUnreadable(iocToCompile.Password, true);
string strAll = strUrl + strUser + strPassword;
char chSep = char.MinValue;
char[] vPrefSeps = new char[]{ '@', '#', '!', '$', '*' };
foreach(char ch in vPrefSeps)
{
if(strAll.IndexOf(ch) < 0)
{
chSep = ch;
break;
}
}
if(chSep == char.MinValue)
{
for(char chEnum = '!'; chEnum < char.MaxValue; ++chEnum)
{
if(strAll.IndexOf(chEnum) < 0)
{
chSep = chEnum;
break;
}
}
}
string strAll = strUrl + strUser + strPassword + "CUN";
char chSep = StrUtil.GetUnusedChar(strAll);
if(chSep == char.MinValue) throw new FormatException(); if(chSep == char.MinValue) throw new FormatException();
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@@ -279,7 +275,7 @@ namespace ModernKeePassLib.Serialization
string str = m_strUrl; string str = m_strUrl;
if(m_strUser.Length > 0) if(m_strUser.Length > 0)
str += @": " + m_strUser; str += " (" + m_strUser + ")";
return str; return str;
} }
@@ -299,30 +295,33 @@ namespace ModernKeePassLib.Serialization
return ioc; return ioc;
} }
public static IOConnectionInfo FromFile(StorageFile file) public static IOConnectionInfo FromFile(StorageFile file)
{ {
IOConnectionInfo ioc = new IOConnectionInfo(); IOConnectionInfo ioc = new IOConnectionInfo();
ioc.Path = file.Path; ioc.Path = file.Path;
ioc.CredSaveMode = IOCredSaveMode.NoSave; ioc.CredSaveMode = IOCredSaveMode.NoSave;
ioc.StorageFile = file; ioc.StorageFile = file;
return ioc; return ioc;
} }
public bool CanProbablyAccess()
public bool CanProbablyAccess()
{ {
Debug.Assert(false, "not yet implemented"); #if PCL
return false; if(IsLocalFile())
#if TODO return (StorageFile.IsAvailable);
#else
if(IsLocalFile()) return File.Exists(m_strUrl); if(IsLocalFile()) return File.Exists(m_strUrl);
#endif
return true; return true;
#endif
} }
public bool IsLocalFile() public bool IsLocalFile()
{ {
// Not just ":/", see e.g. AppConfigEx.ChangePathRelAbs
return (m_strUrl.IndexOf(@"://") < 0); return (m_strUrl.IndexOf(@"://") < 0);
} }
@@ -355,15 +354,5 @@ namespace ModernKeePassLib.Serialization
m_ioCredProtMode = IOCredProtMode.None; m_ioCredProtMode = IOCredProtMode.None;
} }
} }
public override bool Equals(object obj)
{
if (!(obj is IOConnectionInfo)) return false;
IOConnectionInfo ioc = obj as IOConnectionInfo;
if (ioc.Path != this.Path) return false;
if (ioc.UserName != this.UserName) return false;
if (ioc.Password != this.Password) return false;
return true;
}
} }
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -19,17 +19,27 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
//using System.Drawing; using System.Text;
using System.Security;
using System.Xml; using System.Xml;
using System.IO; using System.IO;
using System.Diagnostics;
using ModernKeePassLib;
using ModernKeePassLib.Collections; using ModernKeePassLib.Collections;
using ModernKeePassLib.Cryptography;
using ModernKeePassLib.Cryptography.Cipher;
using ModernKeePassLib.Interfaces; using ModernKeePassLib.Interfaces;
using ModernKeePassLib.Resources;
using ModernKeePassLib.Security; using ModernKeePassLib.Security;
using ModernKeePassLib.Utility; using ModernKeePassLib.Utility;
namespace ModernKeePassLib.Serialization namespace ModernKeePassLib.Serialization
{ {
public sealed partial class Kdb4File /// <summary>
/// Serialization to KeePass KDBX files.
/// </summary>
public sealed partial class KdbxFile
{ {
private enum KdbContext private enum KdbContext
{ {
@@ -88,13 +98,17 @@ namespace ModernKeePassLib.Serialization
xrs.IgnoreProcessingInstructions = true; xrs.IgnoreProcessingInstructions = true;
xrs.IgnoreWhitespace = true; xrs.IgnoreWhitespace = true;
#if !KeePassLibSD && TODO #if !PCL
// these are default values, so no need to set them
#if !KeePassRT
#if !KeePassLibSD
xrs.ProhibitDtd = true; xrs.ProhibitDtd = true;
#endif #endif
#if TODO
xrs.ValidationType = ValidationType.None; xrs.ValidationType = ValidationType.None;
#endif #endif
#endif
return xrs; return xrs;
} }
@@ -199,6 +213,17 @@ namespace ModernKeePassLib.Serialization
case KdbContext.Meta: case KdbContext.Meta:
if(xr.Name == ElemGenerator) if(xr.Name == ElemGenerator)
ReadString(xr); // Ignore ReadString(xr); // Ignore
else if(xr.Name == ElemHeaderHash)
{
string strHash = ReadString(xr);
if(!string.IsNullOrEmpty(strHash) && (m_pbHashOfHeader != null) &&
!m_bRepairMode)
{
byte[] pbHash = Convert.FromBase64String(strHash);
if(!MemUtil.ArraysEqual(pbHash, m_pbHashOfHeader))
throw new IOException(KLRes.FileCorrupted);
}
}
else if(xr.Name == ElemDbName) else if(xr.Name == ElemDbName)
m_pwDatabase.Name = ReadString(xr); m_pwDatabase.Name = ReadString(xr);
else if(xr.Name == ElemDbNameChanged) else if(xr.Name == ElemDbNameChanged)
@@ -216,10 +241,8 @@ namespace ModernKeePassLib.Serialization
else if(xr.Name == ElemDbColor) else if(xr.Name == ElemDbColor)
{ {
string strColor = ReadString(xr); string strColor = ReadString(xr);
#if TODO /*if(!string.IsNullOrEmpty(strColor))
if(!string.IsNullOrEmpty(strColor)) m_pwDatabase.Color = ColorTranslator.FromHtml(strColor);*/
m_pwDatabase.Color = ColorTranslator.FromHtml(strColor);
#endif
} }
else if(xr.Name == ElemDbKeyChanged) else if(xr.Name == ElemDbKeyChanged)
m_pwDatabase.MasterKeyChanged = ReadTime(xr); m_pwDatabase.MasterKeyChanged = ReadTime(xr);
@@ -390,19 +413,14 @@ namespace ModernKeePassLib.Serialization
else if(xr.Name == ElemFgColor) else if(xr.Name == ElemFgColor)
{ {
string strColor = ReadString(xr); string strColor = ReadString(xr);
#if TODO /*if(!string.IsNullOrEmpty(strColor))
if(!string.IsNullOrEmpty(strColor)) m_ctxEntry.ForegroundColor = ColorTranslator.FromHtml(strColor);*/
m_ctxEntry.ForegroundColor = ColorTranslator.FromHtml(strColor);
#endif
} }
else if(xr.Name == ElemBgColor) else if(xr.Name == ElemBgColor)
{ {
string strColor = ReadString(xr); string strColor = ReadString(xr);
#if TODO /*if(!string.IsNullOrEmpty(strColor))
if(!string.IsNullOrEmpty(strColor)) m_ctxEntry.BackgroundColor = ColorTranslator.FromHtml(strColor);*/
m_ctxEntry.BackgroundColor = ColorTranslator.FromHtml(strColor);
#endif
} }
else if(xr.Name == ElemOverrideUrl) else if(xr.Name == ElemOverrideUrl)
m_ctxEntry.OverrideUrl = ReadString(xr); m_ctxEntry.OverrideUrl = ReadString(xr);
@@ -436,10 +454,10 @@ namespace ModernKeePassLib.Serialization
(ITimeLogger)m_ctxGroup : (ITimeLogger)m_ctxEntry); (ITimeLogger)m_ctxGroup : (ITimeLogger)m_ctxEntry);
Debug.Assert(tl != null); Debug.Assert(tl != null);
if(xr.Name == ElemLastModTime) if(xr.Name == ElemCreationTime)
tl.LastModificationTime = ReadTime(xr);
else if(xr.Name == ElemCreationTime)
tl.CreationTime = ReadTime(xr); tl.CreationTime = ReadTime(xr);
else if(xr.Name == ElemLastModTime)
tl.LastModificationTime = ReadTime(xr);
else if(xr.Name == ElemLastAccessTime) else if(xr.Name == ElemLastAccessTime)
tl.LastAccessTime = ReadTime(xr); tl.LastAccessTime = ReadTime(xr);
else if(xr.Name == ElemExpiryTime) else if(xr.Name == ElemExpiryTime)
@@ -545,7 +563,8 @@ namespace ModernKeePassLib.Serialization
return KdbContext.Meta; return KdbContext.Meta;
else if((ctx == KdbContext.CustomIcon) && (xr.Name == ElemCustomIconItem)) else if((ctx == KdbContext.CustomIcon) && (xr.Name == ElemCustomIconItem))
{ {
if((m_uuidCustomIconID != PwUuid.Zero) && (m_pbCustomIconData != null)) if(!m_uuidCustomIconID.Equals(PwUuid.Zero) &&
(m_pbCustomIconData != null))
m_pwDatabase.CustomIcons.Add(new PwCustomIcon( m_pwDatabase.CustomIcons.Add(new PwCustomIcon(
m_uuidCustomIconID, m_pbCustomIconData)); m_uuidCustomIconID, m_pbCustomIconData));
else { Debug.Assert(false); } else { Debug.Assert(false); }
@@ -572,7 +591,7 @@ namespace ModernKeePassLib.Serialization
} }
else if((ctx == KdbContext.Group) && (xr.Name == ElemGroup)) else if((ctx == KdbContext.Group) && (xr.Name == ElemGroup))
{ {
if(PwUuid.Zero.EqualsValue(m_ctxGroup.Uuid)) if(PwUuid.Zero.Equals(m_ctxGroup.Uuid))
m_ctxGroup.Uuid = new PwUuid(true); // No assert (import) m_ctxGroup.Uuid = new PwUuid(true); // No assert (import)
m_ctxGroups.Pop(); m_ctxGroups.Pop();
@@ -593,7 +612,7 @@ namespace ModernKeePassLib.Serialization
else if((ctx == KdbContext.Entry) && (xr.Name == ElemEntry)) else if((ctx == KdbContext.Entry) && (xr.Name == ElemEntry))
{ {
// Create new UUID if absent // Create new UUID if absent
if(PwUuid.Zero.EqualsValue(m_ctxEntry.Uuid)) if(PwUuid.Zero.Equals(m_ctxEntry.Uuid))
m_ctxEntry.Uuid = new PwUuid(true); // No assert (import) m_ctxEntry.Uuid = new PwUuid(true); // No assert (import)
if(m_bEntryInHistory) if(m_bEntryInHistory)
@@ -670,13 +689,21 @@ namespace ModernKeePassLib.Serialization
} }
m_bReadNextNode = false; // ReadElementString skips end tag m_bReadNextNode = false; // ReadElementString skips end tag
#if PCL
return xr.ReadElementContentAsString(); return xr.ReadElementContentAsString();
#else
return xr.ReadElementString();
#endif
} }
private string ReadStringRaw(XmlReader xr) private string ReadStringRaw(XmlReader xr)
{ {
m_bReadNextNode = false; // ReadElementString skips end tag m_bReadNextNode = false; // ReadElementString skips end tag
return xr.ReadElementContentAsString(); #if PCL
return xr.ReadElementContentAsString();
#else
return xr.ReadElementString();
#endif
} }
private bool ReadBool(XmlReader xr, bool bDefault) private bool ReadBool(XmlReader xr, bool bDefault)
@@ -701,6 +728,9 @@ namespace ModernKeePassLib.Serialization
string str = ReadString(xr); string str = ReadString(xr);
int n; int n;
if(StrUtil.TryParseIntInvariant(str, out n)) return n;
// Backward compatibility
if(StrUtil.TryParseInt(str, out n)) return n; if(StrUtil.TryParseInt(str, out n)) return n;
Debug.Assert(false); Debug.Assert(false);
@@ -712,6 +742,9 @@ namespace ModernKeePassLib.Serialization
string str = ReadString(xr); string str = ReadString(xr);
uint u; uint u;
if(StrUtil.TryParseUIntInvariant(str, out u)) return u;
// Backward compatibility
if(StrUtil.TryParseUInt(str, out u)) return u; if(StrUtil.TryParseUInt(str, out u)) return u;
Debug.Assert(false); Debug.Assert(false);
@@ -723,6 +756,9 @@ namespace ModernKeePassLib.Serialization
string str = ReadString(xr); string str = ReadString(xr);
long l; long l;
if(StrUtil.TryParseLongInvariant(str, out l)) return l;
// Backward compatibility
if(StrUtil.TryParseLong(str, out l)) return l; if(StrUtil.TryParseLong(str, out l)) return l;
Debug.Assert(false); Debug.Assert(false);
@@ -734,6 +770,9 @@ namespace ModernKeePassLib.Serialization
string str = ReadString(xr); string str = ReadString(xr);
ulong u; ulong u;
if(StrUtil.TryParseULongInvariant(str, out u)) return u;
// Backward compatibility
if(StrUtil.TryParseULong(str, out u)) return u; if(StrUtil.TryParseULong(str, out u)) return u;
Debug.Assert(false); Debug.Assert(false);
@@ -757,7 +796,7 @@ namespace ModernKeePassLib.Serialization
if(xb != null) return new ProtectedString(true, xb); if(xb != null) return new ProtectedString(true, xb);
bool bProtect = false; bool bProtect = false;
if(m_format == Kdb4Format.PlainXml) if(m_format == KdbxFormat.PlainXml)
{ {
if(xr.MoveToAttribute(AttrProtectedInMemPlainXml)) if(xr.MoveToAttribute(AttrProtectedInMemPlainXml))
{ {

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -21,12 +21,20 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.IO; using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Security; using System.Security;
#if PCL
using Windows.Security.Cryptography;
#else
using System.Security.Cryptography;
#endif
using System.Xml;
using Windows.Security.Cryptography.Core;
#if !KeePassLibSD #if !KeePassLibSD
using System.IO.Compression; using System.IO.Compression;
#else #else
using ModernKeePassLibSD; using KeePassLibSD;
#endif #endif
using ModernKeePassLib.Cryptography; using ModernKeePassLib.Cryptography;
@@ -35,41 +43,35 @@ using ModernKeePassLib.Interfaces;
using ModernKeePassLib.Keys; using ModernKeePassLib.Keys;
using ModernKeePassLib.Resources; using ModernKeePassLib.Resources;
using ModernKeePassLib.Utility; using ModernKeePassLib.Utility;
using System.Threading.Tasks;
namespace ModernKeePassLib.Serialization namespace ModernKeePassLib.Serialization
{ {
/// <summary> /// <summary>
/// Serialization to KeePass KDBX files. /// Serialization to KeePass KDBX files.
/// </summary> /// </summary>
public sealed partial class Kdb4File public sealed partial class KdbxFile
{ {
private IOConnection m_connection;
/// <summary> /// <summary>
/// Load a KDB file from a file. /// Load a KDB file from a file.
/// </summary> /// </summary>
/// <param name="strFilePath">File to load.</param> /// <param name="strFilePath">File to load.</param>
/// <param name="kdbFormat">Format specifier.</param> /// <param name="kdbFormat">Format specifier.</param>
/// <param name="slLogger">Status logger (optional).</param> /// <param name="slLogger">Status logger (optional).</param>
public async Task Load(string strFilePath, Kdb4Format kdbFormat, IStatusLogger slLogger) public void Load(string strFilePath, KdbxFormat kdbFormat, IStatusLogger slLogger)
{ {
IOConnectionInfo ioc = IOConnectionInfo.FromPath(strFilePath); IOConnectionInfo ioc = IOConnectionInfo.FromPath(strFilePath);
IOConnection ioConnection = new IOConnection(); Load(IOConnection.OpenRead(ioc), kdbFormat, slLogger);
Stream abc = await ioConnection.OpenRead(ioc);
Load(abc, kdbFormat, slLogger);
} }
/// <summary> /// <summary>
/// Load a KDB file from a stream. /// Load a KDB file from a stream.
/// </summary> /// </summary>
/// <param name="sSource">Stream to read the data from. Must contain /// <param name="sSource">Stream to read the data from. Must contain
/// a KDB4 stream.</param> /// a KDBX stream.</param>
/// <param name="kdbFormat">Format specifier.</param> /// <param name="kdbFormat">Format specifier.</param>
/// <param name="slLogger">Status logger (optional).</param> /// <param name="slLogger">Status logger (optional).</param>
public void Load(Stream sSource, Kdb4Format kdbFormat, IStatusLogger slLogger) public void Load(Stream sSource, KdbxFormat kdbFormat, IStatusLogger slLogger)
{ {
Debug.Assert(sSource != null); Debug.Assert(sSource != null);
if(sSource == null) throw new ArgumentNullException("sSource"); if(sSource == null) throw new ArgumentNullException("sSource");
@@ -85,7 +87,7 @@ namespace ModernKeePassLib.Serialization
BinaryReaderEx brDecrypted = null; BinaryReaderEx brDecrypted = null;
Stream readerStream = null; Stream readerStream = null;
if(kdbFormat == Kdb4Format.Default) if(kdbFormat == KdbxFormat.Default)
{ {
br = new BinaryReaderEx(hashedStream, encNoBom, KLRes.FileCorrupted); br = new BinaryReaderEx(hashedStream, encNoBom, KLRes.FileCorrupted);
ReadHeader(br); ReadHeader(br);
@@ -113,11 +115,11 @@ namespace ModernKeePassLib.Serialization
readerStream = new GZipStream(sHashed, CompressionMode.Decompress); readerStream = new GZipStream(sHashed, CompressionMode.Decompress);
else readerStream = sHashed; else readerStream = sHashed;
} }
else if(kdbFormat == Kdb4Format.PlainXml) else if(kdbFormat == KdbxFormat.PlainXml)
readerStream = hashedStream; readerStream = hashedStream;
else { Debug.Assert(false); throw new FormatException("KdbFormat"); } else { Debug.Assert(false); throw new FormatException("KdbFormat"); }
if(kdbFormat != Kdb4Format.PlainXml) // Is an encrypted format if(kdbFormat != KdbxFormat.PlainXml) // Is an encrypted format
{ {
if(m_pbProtectedStreamKey == null) if(m_pbProtectedStreamKey == null)
{ {
@@ -130,53 +132,64 @@ namespace ModernKeePassLib.Serialization
} }
else m_randomStream = null; // No random stream for plain-text files else m_randomStream = null; // No random stream for plain-text files
#if KeePassDebug_WriteXml
// FileStream fsOut = new FileStream("Raw.xml", FileMode.Create,
// FileAccess.Write, FileShare.None);
// try
// {
// while(true)
// {
// int b = readerStream.ReadByte();
// if(b == -1) break;
// fsOut.WriteByte((byte)b);
// }
// }
// catch(Exception) { }
// fsOut.Close();
#endif
ReadXmlStreamed(readerStream, hashedStream); ReadXmlStreamed(readerStream, hashedStream);
// ReadXmlDom(readerStream); // ReadXmlDom(readerStream);
#if !KeePassWinRT readerStream.Dispose();
readerStream.Close(); // GC.KeepAlive(br);
#endif // GC.KeepAlive(brDecrypted);
GC.KeepAlive(brDecrypted);
GC.KeepAlive(br);
} }
#if !KeePassWinRT #if !PCL
catch(CryptographicException) // Thrown on invalid padding catch(CryptographicException) // Thrown on invalid padding
{ {
throw new CryptographicException(KLRes.FileCorrupted); throw new CryptographicException(KLRes.FileCorrupted);
} }
#endif #endif
finally { CommonCleanUpRead(sSource, hashedStream); } finally { CommonCleanUpRead(sSource, hashedStream); }
} }
private void CommonCleanUpRead(Stream sSource, HashingStreamEx hashedStream) private void CommonCleanUpRead(Stream sSource, HashingStreamEx hashedStream)
{ {
m_pbHashOfFileOnDisk = hashedStream.Hash; hashedStream.Dispose();
// Reset memory protection settings (to always use reasonable m_pbHashOfFileOnDisk = hashedStream.Hash;
// defaults)
m_pwDatabase.MemoryProtection = new MemoryProtectionConfig();
return; sSource.Dispose();
#if !KeePassWinRT // Reset memory protection settings (to always use reasonable
// Remove old backups (this call is required here in order to apply // defaults)
// the default history maintenance settings for people upgrading from m_pwDatabase.MemoryProtection = new MemoryProtectionConfig();
// KeePass <= 2.14 to >= 2.15; also it ensures history integrity in
// case a different application has created the KDBX file and ignored
// the history maintenance settings)
m_pwDatabase.MaintainBackups(); // Don't mark database as modified
// Remove old backups (this call is required here in order to apply
// the default history maintenance settings for people upgrading from
// KeePass <= 2.14 to >= 2.15; also it ensures history integrity in
// case a different application has created the KDBX file and ignored
// the history maintenance settings)
m_pwDatabase.MaintainBackups(); // Don't mark database as modified
// Is it ok to leave the stream open ???? m_pbHashOfHeader = null;
hashedStream.Close(); }
sSource.Close();
#endif
}
private void ReadHeader(BinaryReaderEx br) private void ReadHeader(BinaryReaderEx br)
{ {
Debug.Assert(br != null); MemoryStream msHeader = new MemoryStream();
if(br == null) throw new ArgumentNullException("br"); Debug.Assert(br.CopyDataTo == null);
br.CopyDataTo = msHeader;
byte[] pbSig1 = br.ReadBytes(4); byte[] pbSig1 = br.ReadBytes(4);
uint uSig1 = MemUtil.BytesToUInt32(pbSig1); uint uSig1 = MemUtil.BytesToUInt32(pbSig1);
@@ -194,19 +207,27 @@ namespace ModernKeePassLib.Serialization
byte[] pb = br.ReadBytes(4); byte[] pb = br.ReadBytes(4);
uint uVersion = MemUtil.BytesToUInt32(pb); uint uVersion = MemUtil.BytesToUInt32(pb);
if((uVersion & FileVersionCriticalMask) > (FileVersion32 & FileVersionCriticalMask))
if ((uVersion & FileVersionCriticalMask) > (FileVersion32 & FileVersionCriticalMask))
#if TODO
throw new FormatException(KLRes.FileVersionUnsupported + throw new FormatException(KLRes.FileVersionUnsupported +
MessageService.NewParagraph + KLRes.FileNewVerReq); Environment.NewLine + Environment.NewLine + KLRes.FileNewVerReq);
#else
throw new FormatException();
#endif
while(true) while(true)
{ {
if(ReadHeaderField(br) == false) if(ReadHeaderField(br) == false)
break; break;
} }
br.CopyDataTo = null;
byte[] pbHeader = msHeader.ToArray();
msHeader.Dispose();
#if PCL
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
m_pbHashOfHeader = sha256.HashData(pbHeader.AsBuffer()).ToArray();
#else
SHA256Managed sha256 = new SHA256Managed();
m_pbHashOfHeader = sha256.ComputeHash(pbHeader);
#endif
} }
private bool ReadHeaderField(BinaryReaderEx brSource) private bool ReadHeaderField(BinaryReaderEx brSource)
@@ -229,49 +250,49 @@ namespace ModernKeePassLib.Serialization
} }
bool bResult = true; bool bResult = true;
Kdb4HeaderFieldID kdbID = (Kdb4HeaderFieldID)btFieldID; KdbxHeaderFieldID kdbID = (KdbxHeaderFieldID)btFieldID;
switch(kdbID) switch(kdbID)
{ {
case Kdb4HeaderFieldID.EndOfHeader: case KdbxHeaderFieldID.EndOfHeader:
bResult = false; // Returning false indicates end of header bResult = false; // Returning false indicates end of header
break; break;
case Kdb4HeaderFieldID.CipherID: case KdbxHeaderFieldID.CipherID:
SetCipher(pbData); SetCipher(pbData);
break; break;
case Kdb4HeaderFieldID.CompressionFlags: case KdbxHeaderFieldID.CompressionFlags:
SetCompressionFlags(pbData); SetCompressionFlags(pbData);
break; break;
case Kdb4HeaderFieldID.MasterSeed: case KdbxHeaderFieldID.MasterSeed:
m_pbMasterSeed = pbData; m_pbMasterSeed = pbData;
CryptoRandom.Instance.AddEntropy(pbData); CryptoRandom.Instance.AddEntropy(pbData);
break; break;
case Kdb4HeaderFieldID.TransformSeed: case KdbxHeaderFieldID.TransformSeed:
m_pbTransformSeed = pbData; m_pbTransformSeed = pbData;
CryptoRandom.Instance.AddEntropy(pbData); CryptoRandom.Instance.AddEntropy(pbData);
break; break;
case Kdb4HeaderFieldID.TransformRounds: case KdbxHeaderFieldID.TransformRounds:
m_pwDatabase.KeyEncryptionRounds = MemUtil.BytesToUInt64(pbData); m_pwDatabase.KeyEncryptionRounds = MemUtil.BytesToUInt64(pbData);
break; break;
case Kdb4HeaderFieldID.EncryptionIV: case KdbxHeaderFieldID.EncryptionIV:
m_pbEncryptionIV = pbData; m_pbEncryptionIV = pbData;
break; break;
case Kdb4HeaderFieldID.ProtectedStreamKey: case KdbxHeaderFieldID.ProtectedStreamKey:
m_pbProtectedStreamKey = pbData; m_pbProtectedStreamKey = pbData;
CryptoRandom.Instance.AddEntropy(pbData); CryptoRandom.Instance.AddEntropy(pbData);
break; break;
case Kdb4HeaderFieldID.StreamStartBytes: case KdbxHeaderFieldID.StreamStartBytes:
m_pbStreamStartBytes = pbData; m_pbStreamStartBytes = pbData;
break; break;
case Kdb4HeaderFieldID.InnerRandomStreamID: case KdbxHeaderFieldID.InnerRandomStreamID:
SetInnerRandomStreamID(pbData); SetInnerRandomStreamID(pbData);
break; break;
@@ -312,45 +333,38 @@ namespace ModernKeePassLib.Serialization
m_craInnerRandomStream = (CrsAlgorithm)uID; m_craInnerRandomStream = (CrsAlgorithm)uID;
} }
private Stream AttachStreamDecryptor(Stream s) private Stream AttachStreamDecryptor(Stream s)
{ {
MemoryStream ms = new MemoryStream(); using (var ms = new MemoryStream())
{
Debug.Assert(m_pbMasterSeed.Length == 32);
if (m_pbMasterSeed.Length != 32)
throw new FormatException(KLRes.MasterSeedLengthInvalid);
ms.Write(m_pbMasterSeed, 0, 32);
Debug.Assert(m_pbMasterSeed.Length == 32); byte[] pKey32 = m_pwDatabase.MasterKey.GenerateKey32(m_pbTransformSeed,
if(m_pbMasterSeed.Length != 32) m_pwDatabase.KeyEncryptionRounds).ReadData();
throw new FormatException(KLRes.MasterSeedLengthInvalid); if (pKey32 == null || pKey32.Length != 32)
ms.Write(m_pbMasterSeed, 0, 32); throw new SecurityException(KLRes.InvalidCompositeKey);
ms.Write(pKey32, 0, 32);
Security.ProtectedBinary pb = m_pwDatabase.MasterKey.GenerateKey32(m_pbTransformSeed, #if PCL
m_pwDatabase.KeyEncryptionRounds); var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
var aesKey = sha256.HashData(ms.GetWindowsRuntimeBuffer()).ToArray();
#else
SHA256Managed sha256 = new SHA256Managed();
byte[] aesKey = sha256.ComputeHash(ms.ToArray());
#endif
Array.Clear(pKey32, 0, 32);
byte[] pKey32 = pb.ReadData(); if (aesKey == null || aesKey.Length != 32)
if((pKey32 == null) || (pKey32.Length != 32)) throw new SecurityException(KLRes.FinalKeyCreationFailed);
throw new SecurityException(KLRes.InvalidCompositeKey);
ms.Write(pKey32, 0, 32);
byte[] aesKey = SHA256Managed.Instance.ComputeHash(ms.ToArray()); ICipherEngine iEngine = CipherPool.GlobalPool.GetCipher(m_pwDatabase.DataCipherUuid);
if (iEngine == null) throw new SecurityException(KLRes.FileUnknownCipher);
//SHA256Managed sha256 = new SHA256Managed(); return iEngine.DecryptStream(s, aesKey, m_pbEncryptionIV);
//byte[] aesKey = sha256.ComputeHash(ms.ToArray()); }
}
//ms.Close();
Array.Clear(pKey32, 0, 32);
if((aesKey == null) || (aesKey.Length != 32))
throw new SecurityException(KLRes.FinalKeyCreationFailed);
ICipherEngine iEngine = CipherPool.GlobalPool.GetCipher(m_pwDatabase.DataCipherUuid);
if(iEngine == null) throw new SecurityException(KLRes.FileUnknownCipher);
return iEngine.DecryptStream(s, aesKey, m_pbEncryptionIV);
}
[Obsolete]
public static List<PwEntry> ReadEntries(PwDatabase pwDatabase, Stream msData)
{
return ReadEntries(msData);
}
/// <summary> /// <summary>
/// Read entries from a stream. /// Read entries from a stream.
@@ -359,11 +373,8 @@ namespace ModernKeePassLib.Serialization
/// <returns>Extracted entries.</returns> /// <returns>Extracted entries.</returns>
public static List<PwEntry> ReadEntries(Stream msData) public static List<PwEntry> ReadEntries(Stream msData)
{ {
Debug.Assert(false, "not yet implemented"); /* KdbxFile f = new KdbxFile(pwDatabase);
return null; f.m_format = KdbxFormat.PlainXml;
#if TODO
/* Kdb4File f = new Kdb4File(pwDatabase);
f.m_format = Kdb4Format.PlainXml;
XmlDocument doc = new XmlDocument(); XmlDocument doc = new XmlDocument();
doc.Load(msData); doc.Load(msData);
@@ -391,8 +402,8 @@ namespace ModernKeePassLib.Serialization
return vEntries; */ return vEntries; */
PwDatabase pd = new PwDatabase(); PwDatabase pd = new PwDatabase();
Kdb4File f = new Kdb4File(pd); KdbxFile f = new KdbxFile(pd);
f.Load(msData, Kdb4Format.PlainXml, null); f.Load(msData, KdbxFormat.PlainXml, null);
List<PwEntry> vEntries = new List<PwEntry>(); List<PwEntry> vEntries = new List<PwEntry>();
foreach(PwEntry pe in pd.RootGroup.Entries) foreach(PwEntry pe in pd.RootGroup.Entries)
@@ -402,7 +413,6 @@ namespace ModernKeePassLib.Serialization
} }
return vEntries; return vEntries;
#endif
} }
} }
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -19,39 +19,43 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Security;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.IO;
using System.Xml; using System.Xml;
//using System.Drawing; using System.Security;
//using System.Drawing.Imaging; #if PCL
using Windows.Security.Cryptography;
#if !KeePassLibSD
#else #else
using ModernKeePassLibSD; using System.Security.Cryptography;
#endif
using System.Globalization;
using System.Diagnostics;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Security.Cryptography.Core;
#if !KeePassLibSD
using System.IO.Compression;
#else
using KeePassLibSD;
#endif #endif
using ModernKeePassLib.Collections; using ModernKeePassLib.Collections;
using ModernKeePassLib.Cryptography; using ModernKeePassLib.Cryptography;
using ModernKeePassLib.Cryptography.Cipher; using ModernKeePassLib.Cryptography.Cipher;
using ModernKeePassLib.Delegates;
using ModernKeePassLib.Interfaces; using ModernKeePassLib.Interfaces;
using ModernKeePassLib.Keys; using ModernKeePassLib.Keys;
using ModernKeePassLib.Resources; using ModernKeePassLib.Resources;
using ModernKeePassLib.Security; using ModernKeePassLib.Security;
using ModernKeePassLib.Utility; using ModernKeePassLib.Utility;
using ModernKeePassLib.Delegates;
namespace ModernKeePassLib.Serialization namespace ModernKeePassLib.Serialization
{ {
/// <summary> /// <summary>
/// Serialization to KeePass KDB files. /// Serialization to KeePass KDBX files.
/// </summary> /// </summary>
public sealed partial class Kdb4File public sealed partial class KdbxFile
{ {
// public void Save(string strFile, PwGroup pgDataSource, Kdb4Format format, // public void Save(string strFile, PwGroup pgDataSource, KdbxFormat format,
// IStatusLogger slLogger) // IStatusLogger slLogger)
// { // {
// bool bMadeUnhidden = UrlUtil.UnhideFile(strFile); // bool bMadeUnhidden = UrlUtil.UnhideFile(strFile);
@@ -71,7 +75,7 @@ namespace ModernKeePassLib.Serialization
/// be written.</param> /// be written.</param>
/// <param name="format">Format of the file to create.</param> /// <param name="format">Format of the file to create.</param>
/// <param name="slLogger">Logger that recieves status information.</param> /// <param name="slLogger">Logger that recieves status information.</param>
public void Save(Stream sSaveTo, PwGroup pgDataSource, Kdb4Format format, public void Save(Stream sSaveTo, PwGroup pgDataSource, KdbxFormat format,
IStatusLogger slLogger) IStatusLogger slLogger)
{ {
Debug.Assert(sSaveTo != null); Debug.Assert(sSaveTo != null);
@@ -85,152 +89,167 @@ namespace ModernKeePassLib.Serialization
UTF8Encoding encNoBom = StrUtil.Utf8; UTF8Encoding encNoBom = StrUtil.Utf8;
CryptoRandom cr = CryptoRandom.Instance; CryptoRandom cr = CryptoRandom.Instance;
try try
{ {
m_pbMasterSeed = cr.GetRandomBytes(32); m_pbMasterSeed = cr.GetRandomBytes(32);
m_pbTransformSeed = cr.GetRandomBytes(32); m_pbTransformSeed = cr.GetRandomBytes(32);
m_pbEncryptionIV = cr.GetRandomBytes(16); m_pbEncryptionIV = cr.GetRandomBytes(16);
m_pbProtectedStreamKey = cr.GetRandomBytes(32); m_pbProtectedStreamKey = cr.GetRandomBytes(32);
m_craInnerRandomStream = CrsAlgorithm.Salsa20; m_craInnerRandomStream = CrsAlgorithm.Salsa20;
m_randomStream = new CryptoRandomStream(m_craInnerRandomStream, m_randomStream = new CryptoRandomStream(m_craInnerRandomStream,
m_pbProtectedStreamKey); m_pbProtectedStreamKey);
m_pbStreamStartBytes = cr.GetRandomBytes(32); m_pbStreamStartBytes = cr.GetRandomBytes(32);
Stream writerStream; Stream writerStream;
BinaryWriter bw = null; if(m_format == KdbxFormat.Default)
if (m_format == Kdb4Format.Default) {
{ WriteHeader(hashedStream); // Also flushes the stream
bw = new BinaryWriter(hashedStream, encNoBom);
WriteHeader(bw); // Also flushes bw
Stream sEncrypted = AttachStreamEncryptor(hashedStream); Stream sEncrypted = AttachStreamEncryptor(hashedStream);
if ((sEncrypted == null) || (sEncrypted == hashedStream)) if((sEncrypted == null) || (sEncrypted == hashedStream))
throw new SecurityException(KLRes.CryptoStreamFailed); throw new SecurityException(KLRes.CryptoStreamFailed);
sEncrypted.Write(m_pbStreamStartBytes, 0, m_pbStreamStartBytes.Length); sEncrypted.Write(m_pbStreamStartBytes, 0, m_pbStreamStartBytes.Length);
Stream sHashed = new HashedBlockStream(sEncrypted, true); Stream sHashed = new HashedBlockStream(sEncrypted, true);
if (m_pwDatabase.Compression == PwCompressionAlgorithm.GZip) if(m_pwDatabase.Compression == PwCompressionAlgorithm.GZip)
writerStream = new GZipStream(sHashed, CompressionMode.Compress); writerStream = new GZipStream(sHashed, CompressionMode.Compress);
else else
writerStream = sHashed; writerStream = sHashed;
} }
else if (m_format == Kdb4Format.PlainXml) else if(m_format == KdbxFormat.PlainXml)
writerStream = hashedStream; writerStream = hashedStream;
else else { Debug.Assert(false); throw new FormatException("KdbFormat"); }
{
Debug.Assert(false);
throw new FormatException("KdbFormat");
}
using (m_xmlWriter = XmlWriter.Create(writerStream, new XmlWriterSettings {Encoding = encNoBom})) #if PCL
{ var settings = new XmlWriterSettings() {
WriteDocument(pgDataSource); Encoding = encNoBom,
Indent = true,
IndentChars = "\t",
NewLineChars = "\r\n",
};
m_xmlWriter = XmlWriter.Create(writerStream, settings);
#else
m_xmlWriter = new XmlTextWriter(writerStream, encNoBom);
#endif
WriteDocument(pgDataSource);
m_xmlWriter.Flush(); m_xmlWriter.Flush();
writerStream.Dispose(); m_xmlWriter.Dispose();
} writerStream.Dispose();
GC.KeepAlive(bw); }
}
catch (Exception ex)
{
}
finally { CommonCleanUpWrite(sSaveTo, hashedStream); } finally { CommonCleanUpWrite(sSaveTo, hashedStream); }
} }
private void CommonCleanUpWrite(Stream sSaveTo, HashingStreamEx hashedStream) private void CommonCleanUpWrite(Stream sSaveTo, HashingStreamEx hashedStream)
{ {
//hashedStream.Close(); hashedStream.Dispose();
m_pbHashOfFileOnDisk = hashedStream.Hash; m_pbHashOfFileOnDisk = hashedStream.Hash;
sSaveTo.Dispose(); sSaveTo.Dispose();
m_xmlWriter = null; m_xmlWriter = null;
m_pbHashOfHeader = null;
} }
private void WriteHeader(BinaryWriter bw) private void WriteHeader(Stream s)
{ {
Debug.Assert(bw != null); MemoryStream ms = new MemoryStream();
if(bw == null) throw new ArgumentNullException("bw");
bw.Write(MemUtil.UInt32ToBytes(FileSignature1)); MemUtil.Write(ms, MemUtil.UInt32ToBytes(FileSignature1));
bw.Write(MemUtil.UInt32ToBytes(FileSignature2)); MemUtil.Write(ms, MemUtil.UInt32ToBytes(FileSignature2));
bw.Write(MemUtil.UInt32ToBytes(FileVersion32)); MemUtil.Write(ms, MemUtil.UInt32ToBytes(FileVersion32));
WriteHeaderField(bw, Kdb4HeaderFieldID.CipherID, WriteHeaderField(ms, KdbxHeaderFieldID.CipherID,
m_pwDatabase.DataCipherUuid.UuidBytes); m_pwDatabase.DataCipherUuid.UuidBytes);
int nCprID = (int)m_pwDatabase.Compression; int nCprID = (int)m_pwDatabase.Compression;
WriteHeaderField(bw, Kdb4HeaderFieldID.CompressionFlags, WriteHeaderField(ms, KdbxHeaderFieldID.CompressionFlags,
MemUtil.UInt32ToBytes((uint)nCprID)); MemUtil.UInt32ToBytes((uint)nCprID));
WriteHeaderField(bw, Kdb4HeaderFieldID.MasterSeed, m_pbMasterSeed); WriteHeaderField(ms, KdbxHeaderFieldID.MasterSeed, m_pbMasterSeed);
WriteHeaderField(bw, Kdb4HeaderFieldID.TransformSeed, m_pbTransformSeed); WriteHeaderField(ms, KdbxHeaderFieldID.TransformSeed, m_pbTransformSeed);
WriteHeaderField(bw, Kdb4HeaderFieldID.TransformRounds, MemUtil.UInt64ToBytes(m_pwDatabase.KeyEncryptionRounds)); WriteHeaderField(ms, KdbxHeaderFieldID.TransformRounds,
WriteHeaderField(bw, Kdb4HeaderFieldID.EncryptionIV, m_pbEncryptionIV); MemUtil.UInt64ToBytes(m_pwDatabase.KeyEncryptionRounds));
WriteHeaderField(bw, Kdb4HeaderFieldID.ProtectedStreamKey, m_pbProtectedStreamKey); WriteHeaderField(ms, KdbxHeaderFieldID.EncryptionIV, m_pbEncryptionIV);
WriteHeaderField(bw, Kdb4HeaderFieldID.StreamStartBytes, m_pbStreamStartBytes); WriteHeaderField(ms, KdbxHeaderFieldID.ProtectedStreamKey, m_pbProtectedStreamKey);
WriteHeaderField(ms, KdbxHeaderFieldID.StreamStartBytes, m_pbStreamStartBytes);
int nIrsID = (int)m_craInnerRandomStream; int nIrsID = (int)m_craInnerRandomStream;
WriteHeaderField(bw, Kdb4HeaderFieldID.InnerRandomStreamID, WriteHeaderField(ms, KdbxHeaderFieldID.InnerRandomStreamID,
MemUtil.UInt32ToBytes((uint)nIrsID)); MemUtil.UInt32ToBytes((uint)nIrsID));
WriteHeaderField(bw, Kdb4HeaderFieldID.EndOfHeader, new byte[]{ (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' }); WriteHeaderField(ms, KdbxHeaderFieldID.EndOfHeader, new byte[]{
bw.Flush(); (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' });
byte[] pbHeader = ms.ToArray();
ms.Dispose();
#if PCL
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
m_pbHashOfHeader = sha256.HashData(pbHeader.AsBuffer()).ToArray();
#else
SHA256Managed sha256 = new SHA256Managed();
m_pbHashOfHeader = sha256.ComputeHash(pbHeader);
#endif
s.Write(pbHeader, 0, pbHeader.Length);
s.Flush();
} }
private static void WriteHeaderField(BinaryWriter bwOut, private static void WriteHeaderField(Stream s, KdbxHeaderFieldID kdbID,
Kdb4HeaderFieldID kdbID, byte[] pbData) byte[] pbData)
{ {
Debug.Assert(bwOut != null); s.WriteByte((byte)kdbID);
if(bwOut == null) throw new ArgumentNullException("bwOut");
bwOut.Write((byte)kdbID);
if(pbData != null) if(pbData != null)
{ {
ushort uLength = (ushort)pbData.Length; ushort uLength = (ushort)pbData.Length;
bwOut.Write(uLength); MemUtil.Write(s, MemUtil.UInt16ToBytes(uLength));
if(uLength > 0) bwOut.Write(pbData); if(uLength > 0) s.Write(pbData, 0, pbData.Length);
} }
else bwOut.Write((ushort)0); else MemUtil.Write(s, MemUtil.UInt16ToBytes((ushort)0));
} }
private Stream AttachStreamEncryptor(Stream s) private Stream AttachStreamEncryptor(Stream s)
{ {
using (MemoryStream ms = new MemoryStream()) MemoryStream ms = new MemoryStream();
{
Debug.Assert(m_pbMasterSeed != null);
Debug.Assert(m_pbMasterSeed.Length == 32);
ms.Write(m_pbMasterSeed, 0, 32);
Debug.Assert(m_pwDatabase != null); Debug.Assert(m_pbMasterSeed != null);
Debug.Assert(m_pwDatabase.MasterKey != null); Debug.Assert(m_pbMasterSeed.Length == 32);
ProtectedBinary pbinKey = m_pwDatabase.MasterKey.GenerateKey32( ms.Write(m_pbMasterSeed, 0, 32);
m_pbTransformSeed, m_pwDatabase.KeyEncryptionRounds);
Debug.Assert(pbinKey != null);
if (pbinKey == null)
throw new SecurityException(KLRes.InvalidCompositeKey);
byte[] pKey32 = pbinKey.ReadData();
if ((pKey32 == null) || (pKey32.Length != 32))
throw new SecurityException(KLRes.InvalidCompositeKey);
ms.Write(pKey32, 0, 32);
SHA256Managed sha256 = SHA256Managed.Instance; Debug.Assert(m_pwDatabase != null);
byte[] aesKey = sha256.ComputeHash(ms.ToArray()); Debug.Assert(m_pwDatabase.MasterKey != null);
ProtectedBinary pbinKey = m_pwDatabase.MasterKey.GenerateKey32(
m_pbTransformSeed, m_pwDatabase.KeyEncryptionRounds);
Debug.Assert(pbinKey != null);
if(pbinKey == null)
throw new SecurityException(KLRes.InvalidCompositeKey);
byte[] pKey32 = pbinKey.ReadData();
if((pKey32 == null) || (pKey32.Length != 32))
throw new SecurityException(KLRes.InvalidCompositeKey);
ms.Write(pKey32, 0, 32);
Array.Clear(pKey32, 0, 32); #if PCL
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
var aesKey = sha256.HashData(ms.GetWindowsRuntimeBuffer()).ToArray();
#else
SHA256Managed sha256 = new SHA256Managed();
byte[] aesKey = sha256.ComputeHash(ms.ToArray());
#endif
Debug.Assert(CipherPool.GlobalPool != null); ms.Dispose();
ICipherEngine iEngine = CipherPool.GlobalPool.GetCipher(m_pwDatabase.DataCipherUuid); Array.Clear(pKey32, 0, 32);
if(iEngine == null) throw new SecurityException(KLRes.FileUnknownCipher);
return iEngine.EncryptStream(s, aesKey, m_pbEncryptionIV); Debug.Assert(CipherPool.GlobalPool != null);
} ICipherEngine iEngine = CipherPool.GlobalPool.GetCipher(m_pwDatabase.DataCipherUuid);
if(iEngine == null) throw new SecurityException(KLRes.FileUnknownCipher);
return iEngine.EncryptStream(s, aesKey, m_pbEncryptionIV);
} }
private void WriteDocument(PwGroup pgDataSource) private void WriteDocument(PwGroup pgDataSource)
@@ -245,8 +264,11 @@ namespace ModernKeePassLib.Serialization
BinPoolBuild(pgRoot); BinPoolBuild(pgRoot);
m_xmlWriter.Settings.Indent = true; #if !PCL
m_xmlWriter.Settings.IndentChars = "\t"; m_xmlWriter.Formatting = Formatting.Indented;
m_xmlWriter.IndentChar = '\t';
m_xmlWriter.Indentation = 1;
#endif
m_xmlWriter.WriteStartDocument(true); m_xmlWriter.WriteStartDocument(true);
m_xmlWriter.WriteStartElement(ElemDocNode); m_xmlWriter.WriteStartElement(ElemDocNode);
@@ -320,6 +342,11 @@ namespace ModernKeePassLib.Serialization
m_xmlWriter.WriteStartElement(ElemMeta); m_xmlWriter.WriteStartElement(ElemMeta);
WriteObject(ElemGenerator, PwDatabase.LocalizedAppName, false); // Generator name WriteObject(ElemGenerator, PwDatabase.LocalizedAppName, false); // Generator name
if(m_pbHashOfHeader != null)
WriteObject(ElemHeaderHash, Convert.ToBase64String(
m_pbHashOfHeader), false);
WriteObject(ElemDbName, m_pwDatabase.Name, true); WriteObject(ElemDbName, m_pwDatabase.Name, true);
WriteObject(ElemDbNameChanged, m_pwDatabase.NameChanged); WriteObject(ElemDbNameChanged, m_pwDatabase.NameChanged);
WriteObject(ElemDbDesc, m_pwDatabase.Description, true); WriteObject(ElemDbDesc, m_pwDatabase.Description, true);
@@ -361,7 +388,7 @@ namespace ModernKeePassLib.Serialization
WriteObject(ElemNotes, pg.Notes, true); WriteObject(ElemNotes, pg.Notes, true);
WriteObject(ElemIcon, (int)pg.IconId); WriteObject(ElemIcon, (int)pg.IconId);
if(pg.CustomIconUuid != PwUuid.Zero) if(!pg.CustomIconUuid.Equals(PwUuid.Zero))
WriteObject(ElemCustomIconID, pg.CustomIconUuid); WriteObject(ElemCustomIconID, pg.CustomIconUuid);
WriteList(ElemTimes, pg); WriteList(ElemTimes, pg);
@@ -386,7 +413,7 @@ namespace ModernKeePassLib.Serialization
WriteObject(ElemUuid, pe.Uuid); WriteObject(ElemUuid, pe.Uuid);
WriteObject(ElemIcon, (int)pe.IconId); WriteObject(ElemIcon, (int)pe.IconId);
if(pe.CustomIconUuid != PwUuid.Zero) if(!pe.CustomIconUuid.Equals(PwUuid.Zero))
WriteObject(ElemCustomIconID, pe.CustomIconUuid); WriteObject(ElemCustomIconID, pe.CustomIconUuid);
WriteObject(ElemFgColor, StrUtil.ColorToUnnamedHtml(pe.ForegroundColor, true), false); WriteObject(ElemFgColor, StrUtil.ColorToUnnamedHtml(pe.ForegroundColor, true), false);
@@ -452,8 +479,8 @@ namespace ModernKeePassLib.Serialization
m_xmlWriter.WriteStartElement(name); m_xmlWriter.WriteStartElement(name);
WriteObject(ElemLastModTime, times.LastModificationTime);
WriteObject(ElemCreationTime, times.CreationTime); WriteObject(ElemCreationTime, times.CreationTime);
WriteObject(ElemLastModTime, times.LastModificationTime);
WriteObject(ElemLastAccessTime, times.LastAccessTime); WriteObject(ElemLastAccessTime, times.LastAccessTime);
WriteObject(ElemExpiryTime, times.ExpiryTime); WriteObject(ElemExpiryTime, times.ExpiryTime);
WriteObject(ElemExpires, times.Expires); WriteObject(ElemExpires, times.Expires);
@@ -575,7 +602,7 @@ namespace ModernKeePassLib.Serialization
Debug.Assert(name != null); Debug.Assert(name != null);
m_xmlWriter.WriteStartElement(name); m_xmlWriter.WriteStartElement(name);
m_xmlWriter.WriteString(value.ToString()); m_xmlWriter.WriteString(value.ToString(NumberFormatInfo.InvariantInfo));
m_xmlWriter.WriteEndElement(); m_xmlWriter.WriteEndElement();
} }
@@ -584,7 +611,7 @@ namespace ModernKeePassLib.Serialization
Debug.Assert(name != null); Debug.Assert(name != null);
m_xmlWriter.WriteStartElement(name); m_xmlWriter.WriteStartElement(name);
m_xmlWriter.WriteString(value.ToString()); m_xmlWriter.WriteString(value.ToString(NumberFormatInfo.InvariantInfo));
m_xmlWriter.WriteEndElement(); m_xmlWriter.WriteEndElement();
} }
@@ -593,7 +620,7 @@ namespace ModernKeePassLib.Serialization
Debug.Assert(name != null); Debug.Assert(name != null);
m_xmlWriter.WriteStartElement(name); m_xmlWriter.WriteStartElement(name);
m_xmlWriter.WriteString(value.ToString()); m_xmlWriter.WriteString(value.ToString(NumberFormatInfo.InvariantInfo));
m_xmlWriter.WriteEndElement(); m_xmlWriter.WriteEndElement();
} }
@@ -602,7 +629,7 @@ namespace ModernKeePassLib.Serialization
Debug.Assert(name != null); Debug.Assert(name != null);
m_xmlWriter.WriteStartElement(name); m_xmlWriter.WriteStartElement(name);
m_xmlWriter.WriteString(value.ToString()); m_xmlWriter.WriteString(value.ToString(NumberFormatInfo.InvariantInfo));
m_xmlWriter.WriteEndElement(); m_xmlWriter.WriteEndElement();
} }
@@ -657,7 +684,7 @@ namespace ModernKeePassLib.Serialization
bProtected = m_pwDatabase.MemoryProtection.ProtectNotes; bProtected = m_pwDatabase.MemoryProtection.ProtectNotes;
} }
if(bProtected && (m_format != Kdb4Format.PlainXml)) if(bProtected && (m_format != KdbxFormat.PlainXml))
{ {
m_xmlWriter.WriteAttributeString(AttrProtected, ValTrue); m_xmlWriter.WriteAttributeString(AttrProtected, ValTrue);
@@ -667,7 +694,6 @@ namespace ModernKeePassLib.Serialization
} }
else else
{ {
string strValue = value.ReadString(); string strValue = value.ReadString();
// If names should be localized, we need to apply the language-dependent // If names should be localized, we need to apply the language-dependent
@@ -685,7 +711,8 @@ namespace ModernKeePassLib.Serialization
// page area // page area
if(char.IsSymbol(ch) || char.IsSurrogate(ch)) if(char.IsSymbol(ch) || char.IsSurrogate(ch))
{ {
UnicodeCategory cat = CharUnicodeInfo.GetUnicodeCategory(ch); System.Globalization.UnicodeCategory cat =
CharUnicodeInfo.GetUnicodeCategory(ch);
// Map character to correct position in code page // Map character to correct position in code page
chMapped = (char)((int)cat * 32 + ch); chMapped = (char)((int)cat * 32 + ch);
} }
@@ -697,7 +724,11 @@ namespace ModernKeePassLib.Serialization
// in the low ANSI range (up to 255) when calling // in the low ANSI range (up to 255) when calling
// ToLower on them with invariant culture (see // ToLower on them with invariant culture (see
// http://lists.ximian.com/pipermail/mono-patches/2002-February/086106.html ) // http://lists.ximian.com/pipermail/mono-patches/2002-February/086106.html )
#if !KeePassLibSD
chMapped = char.ToLowerInvariant(ch); chMapped = char.ToLowerInvariant(ch);
#else
chMapped = char.ToLower(ch);
#endif
} }
} }
@@ -707,8 +738,7 @@ namespace ModernKeePassLib.Serialization
strValue = sb.ToString(); // Correct string for current code page strValue = sb.ToString(); // Correct string for current code page
} }
if((m_format == KdbxFormat.PlainXml) && bProtected)
if((m_format == Kdb4Format.PlainXml) && bProtected)
m_xmlWriter.WriteAttributeString(AttrProtectedInMemPlainXml, ValTrue); m_xmlWriter.WriteAttributeString(AttrProtectedInMemPlainXml, ValTrue);
m_xmlWriter.WriteString(StrUtil.SafeXmlString(strValue)); m_xmlWriter.WriteString(StrUtil.SafeXmlString(strValue));
@@ -716,7 +746,7 @@ namespace ModernKeePassLib.Serialization
m_xmlWriter.WriteEndElement(); // ElemValue m_xmlWriter.WriteEndElement(); // ElemValue
m_xmlWriter.WriteEndElement(); // ElemString m_xmlWriter.WriteEndElement(); // ElemString
} }
private void WriteObject(string name, ProtectedBinary value, bool bAllowRef) private void WriteObject(string name, ProtectedBinary value, bool bAllowRef)
{ {
@@ -742,7 +772,7 @@ namespace ModernKeePassLib.Serialization
private void SubWriteValue(ProtectedBinary value) private void SubWriteValue(ProtectedBinary value)
{ {
if(value.IsProtected && (m_format != Kdb4Format.PlainXml)) if(value.IsProtected && (m_format != KdbxFormat.PlainXml))
{ {
m_xmlWriter.WriteAttributeString(AttrProtected, ValTrue); m_xmlWriter.WriteAttributeString(AttrProtected, ValTrue);
@@ -810,8 +840,8 @@ namespace ModernKeePassLib.Serialization
/// to the stream.</returns> /// to the stream.</returns>
public static bool WriteEntries(Stream msOutput, PwEntry[] vEntries) public static bool WriteEntries(Stream msOutput, PwEntry[] vEntries)
{ {
/* Kdb4File f = new Kdb4File(pwDatabase); /* KdbxFile f = new KdbxFile(pwDatabase);
f.m_format = Kdb4Format.PlainXml; f.m_format = KdbxFormat.PlainXml;
XmlTextWriter xtw = null; XmlTextWriter xtw = null;
try { xtw = new XmlTextWriter(msOutput, StrUtil.Utf8); } try { xtw = new XmlTextWriter(msOutput, StrUtil.Utf8); }
@@ -843,8 +873,8 @@ namespace ModernKeePassLib.Serialization
foreach(PwEntry peCopy in vEntries) foreach(PwEntry peCopy in vEntries)
pd.RootGroup.AddEntry(peCopy.CloneDeep(), true); pd.RootGroup.AddEntry(peCopy.CloneDeep(), true);
Kdb4File f = new Kdb4File(pd); KdbxFile f = new KdbxFile(pd);
f.Save(msOutput, null, Kdb4Format.PlainXml, null); f.Save(msOutput, null, KdbxFormat.PlainXml, null);
return true; return true;
} }
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -29,6 +29,10 @@ using System.Diagnostics;
using System.IO.Compression; using System.IO.Compression;
#endif #endif
#if PCL
using Windows.Storage;
#endif
using ModernKeePassLib.Collections; using ModernKeePassLib.Collections;
using ModernKeePassLib.Cryptography; using ModernKeePassLib.Cryptography;
using ModernKeePassLib.Delegates; using ModernKeePassLib.Delegates;
@@ -39,10 +43,10 @@ using ModernKeePassLib.Utility;
namespace ModernKeePassLib.Serialization namespace ModernKeePassLib.Serialization
{ {
/// <summary> /// <summary>
/// The <c>Kdb4File</c> class supports saving the data to various /// The <c>KdbxFile</c> class supports saving the data to various
/// formats. /// formats.
/// </summary> /// </summary>
public enum Kdb4Format public enum KdbxFormat
{ {
/// <summary> /// <summary>
/// The default, encrypted file format. /// The default, encrypted file format.
@@ -56,37 +60,37 @@ namespace ModernKeePassLib.Serialization
} }
/// <summary> /// <summary>
/// Serialization to KeePass KDB files. /// Serialization to KeePass KDBX files.
/// </summary> /// </summary>
public sealed partial class Kdb4File public sealed partial class KdbxFile
{ {
/// <summary> /// <summary>
/// File identifier, first 32-bit value. /// File identifier, first 32-bit value.
/// </summary> /// </summary>
private const uint FileSignature1 = 0x9AA2D903; internal const uint FileSignature1 = 0x9AA2D903;
/// <summary> /// <summary>
/// File identifier, second 32-bit value. /// File identifier, second 32-bit value.
/// </summary> /// </summary>
private const uint FileSignature2 = 0xB54BFB67; internal const uint FileSignature2 = 0xB54BFB67;
/// <summary> /// <summary>
/// File version of files saved by the current <c>Kdb4File</c> class. /// File version of files saved by the current <c>KdbxFile</c> class.
/// KeePass 2.07 has version 1.01, 2.08 has 1.02, 2.09 has 2.00, /// KeePass 2.07 has version 1.01, 2.08 has 1.02, 2.09 has 2.00,
/// 2.10 has 2.02, 2.11 has 2.04, 2.15 has 3.00. /// 2.10 has 2.02, 2.11 has 2.04, 2.15 has 3.00, 2.20 has 3.01.
/// The first 2 bytes are critical (i.e. loading will fail, if the /// The first 2 bytes are critical (i.e. loading will fail, if the
/// file version is too high), the last 2 bytes are informational. /// file version is too high), the last 2 bytes are informational.
/// </summary> /// </summary>
private const uint FileVersion32 = 0x00030000; private const uint FileVersion32 = 0x00030001;
private const uint FileVersionCriticalMask = 0xFFFF0000; private const uint FileVersionCriticalMask = 0xFFFF0000;
// KeePass 1.x signature // KeePass 1.x signature
private const uint FileSignatureOld1 = 0x9AA2D903; internal const uint FileSignatureOld1 = 0x9AA2D903;
private const uint FileSignatureOld2 = 0xB54BFB65; internal const uint FileSignatureOld2 = 0xB54BFB65;
// KeePass 2.x pre-release (alpha and beta) signature // KeePass 2.x pre-release (alpha and beta) signature
private const uint FileSignaturePreRelease1 = 0x9AA2D903; internal const uint FileSignaturePreRelease1 = 0x9AA2D903;
private const uint FileSignaturePreRelease2 = 0xB54BFB66; internal const uint FileSignaturePreRelease2 = 0xB54BFB66;
private const string ElemDocNode = "KeePassFile"; private const string ElemDocNode = "KeePassFile";
private const string ElemMeta = "Meta"; private const string ElemMeta = "Meta";
@@ -95,6 +99,7 @@ namespace ModernKeePassLib.Serialization
private const string ElemEntry = "Entry"; private const string ElemEntry = "Entry";
private const string ElemGenerator = "Generator"; private const string ElemGenerator = "Generator";
private const string ElemHeaderHash = "HeaderHash";
private const string ElemDbName = "DatabaseName"; private const string ElemDbName = "DatabaseName";
private const string ElemDbNameChanged = "DatabaseNameChanged"; private const string ElemDbNameChanged = "DatabaseNameChanged";
private const string ElemDbDesc = "DatabaseDescription"; private const string ElemDbDesc = "DatabaseDescription";
@@ -190,9 +195,13 @@ namespace ModernKeePassLib.Serialization
private PwDatabase m_pwDatabase; // Not null, see constructor private PwDatabase m_pwDatabase; // Not null, see constructor
#if PCL
private XmlWriter m_xmlWriter = null; private XmlWriter m_xmlWriter = null;
#else
private XmlTextWriter m_xmlWriter = null;
#endif
private CryptoRandomStream m_randomStream = null; private CryptoRandomStream m_randomStream = null;
private Kdb4Format m_format = Kdb4Format.Default; private KdbxFormat m_format = KdbxFormat.Default;
private IStatusLogger m_slLogger = null; private IStatusLogger m_slLogger = null;
private byte[] m_pbMasterSeed = null; private byte[] m_pbMasterSeed = null;
@@ -208,6 +217,7 @@ namespace ModernKeePassLib.Serialization
private Dictionary<string, ProtectedBinary> m_dictBinPool = private Dictionary<string, ProtectedBinary> m_dictBinPool =
new Dictionary<string, ProtectedBinary>(); new Dictionary<string, ProtectedBinary>();
private byte[] m_pbHashOfHeader = null;
private byte[] m_pbHashOfFileOnDisk = null; private byte[] m_pbHashOfFileOnDisk = null;
private readonly DateTime m_dtNow = DateTime.Now; // Cache current time private readonly DateTime m_dtNow = DateTime.Now; // Cache current time
@@ -217,7 +227,7 @@ namespace ModernKeePassLib.Serialization
private const uint NeutralLanguageID = NeutralLanguageOffset + NeutralLanguageIDSec; private const uint NeutralLanguageID = NeutralLanguageOffset + NeutralLanguageIDSec;
private static bool m_bLocalizedNames = false; private static bool m_bLocalizedNames = false;
private enum Kdb4HeaderFieldID : byte private enum KdbxHeaderFieldID : byte
{ {
EndOfHeader = 0, EndOfHeader = 0,
Comment = 1, Comment = 1,
@@ -261,7 +271,7 @@ namespace ModernKeePassLib.Serialization
/// </summary> /// </summary>
/// <param name="pwDataStore">The <c>PwDatabase</c> instance that the /// <param name="pwDataStore">The <c>PwDatabase</c> instance that the
/// class will load file data into or use to create a KDBX file.</param> /// class will load file data into or use to create a KDBX file.</param>
public Kdb4File(PwDatabase pwDataStore) public KdbxFile(PwDatabase pwDataStore)
{ {
Debug.Assert(pwDataStore != null); Debug.Assert(pwDataStore != null);
if(pwDataStore == null) throw new ArgumentNullException("pwDataStore"); if(pwDataStore == null) throw new ArgumentNullException("pwDataStore");
@@ -322,7 +332,8 @@ namespace ModernKeePassLib.Serialization
if(BinPoolFind(pb) != null) return; // Exists already if(BinPoolFind(pb) != null) return; // Exists already
m_dictBinPool.Add(m_dictBinPool.Count.ToString(), pb); m_dictBinPool.Add(m_dictBinPool.Count.ToString(
NumberFormatInfo.InvariantInfo), pb);
} }
private string BinPoolFind(ProtectedBinary pb) private string BinPoolFind(ProtectedBinary pb)
@@ -350,12 +361,6 @@ namespace ModernKeePassLib.Serialization
private static void SaveBinary(string strName, ProtectedBinary pb, private static void SaveBinary(string strName, ProtectedBinary pb,
string strSaveDir) string strSaveDir)
{ {
// TODO Bert: Needs to be implemented.
#if !TODO
Debug.Assert(false,"not implemented");
#else
if(pb == null) { Debug.Assert(false); return; } if(pb == null) { Debug.Assert(false); return; }
if(string.IsNullOrEmpty(strName)) strName = "File.bin"; if(string.IsNullOrEmpty(strName)) strName = "File.bin";
@@ -370,15 +375,28 @@ namespace ModernKeePassLib.Serialization
string strDesc = UrlUtil.StripExtension(strName); string strDesc = UrlUtil.StripExtension(strName);
strPath += strDesc; strPath += strDesc;
if(iTry > 1) strPath += " (" + iTry.ToString() + ")"; if(iTry > 1)
strPath += " (" + iTry.ToString(NumberFormatInfo.InvariantInfo) +
")";
if(!string.IsNullOrEmpty(strExt)) strPath += "." + strExt; if(!string.IsNullOrEmpty(strExt)) strPath += "." + strExt;
++iTry; ++iTry;
} }
#if PCL
while(ApplicationData.Current.RoamingFolder.GetFileAsync(strPath).GetResults() != null);
#else
while(File.Exists(strPath)); while(File.Exists(strPath));
#endif
#if !KeePassLibSD #if PCL
byte[] pbData = pb.ReadData();
var file = ApplicationData.Current.RoamingFolder.GetFileAsync(strPath).GetResults();
using (var stream = file.OpenAsync(FileAccessMode.ReadWrite).GetResults().AsStream()) {
stream.Write (pbData, 0, pbData.Length);
}
MemUtil.ZeroByteArray(pbData);
#elif !KeePassLibSD
byte[] pbData = pb.ReadData(); byte[] pbData = pb.ReadData();
File.WriteAllBytes(strPath, pbData); File.WriteAllBytes(strPath, pbData);
MemUtil.ZeroByteArray(pbData); MemUtil.ZeroByteArray(pbData);
@@ -389,9 +407,6 @@ namespace ModernKeePassLib.Serialization
fs.Write(pbData, 0, pbData.Length); fs.Write(pbData, 0, pbData.Length);
fs.Close(); fs.Close();
#endif #endif
}
#endif // TODO
}
} }
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -19,8 +19,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Text; using System.Text;
using ModernKeePassLib.Resources; using ModernKeePassLib.Resources;
using ModernKeePassLib.Utility; using ModernKeePassLib.Utility;
@@ -41,17 +41,13 @@ namespace ModernKeePassLib.Serialization
{ {
get get
{ {
Debug.Assert(false, "not yet implemented");
return null;
#if TODO
string str = KLRes.OldFormat + ((m_strFormat.Length > 0) ? string str = KLRes.OldFormat + ((m_strFormat.Length > 0) ?
(@" (" + m_strFormat + @")") : string.Empty) + "."; (@" (" + m_strFormat + @")") : string.Empty) + ".";
if(m_type == OldFormatType.KeePass1x) if(m_type == OldFormatType.KeePass1x)
str += MessageService.NewParagraph + KLRes.KeePass1xHint; str += Environment.NewLine + Environment.NewLine + KLRes.KeePass1xHint;
return str; return str;
#endif
} }
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -17,21 +17,14 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
// BERT TODO: Removed completely for the time being */
#if TODO
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.ComponentModel; using System.ComponentModel;
using System.Windows.Forms;
using System.Diagnostics; using System.Diagnostics;
using System.Xml.Serialization; using System.Xml.Serialization;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Security.Cryptography;
using System.Drawing;
using ModernKeePassLib.Utility; using ModernKeePassLib.Utility;
@@ -46,8 +39,8 @@ namespace ModernKeePassLib.Translation
private const string m_strControlRelative = @"%c"; private const string m_strControlRelative = @"%c";
internal const NumberStyles m_nsParser = NumberStyles.AllowLeadingSign | internal const NumberStyles m_nsParser = (NumberStyles.AllowLeadingSign |
NumberStyles.AllowDecimalPoint; NumberStyles.AllowDecimalPoint);
internal static readonly CultureInfo m_lclInv = CultureInfo.InvariantCulture; internal static readonly CultureInfo m_lclInv = CultureInfo.InvariantCulture;
private string m_strPosX = string.Empty; private string m_strPosX = string.Empty;
@@ -116,7 +109,7 @@ namespace ModernKeePassLib.Translation
else { Debug.Assert(false); } else { Debug.Assert(false); }
} }
#if !KeePassLibSD #if (!KeePassLibSD && !KeePassRT)
internal void ApplyTo(Control c) internal void ApplyTo(Control c)
{ {
Debug.Assert(c != null); if(c == null) return; Debug.Assert(c != null); if(c == null) return;
@@ -271,7 +264,7 @@ namespace ModernKeePassLib.Translation
return m_strMemberName.CompareTo(kpOther.Name); return m_strMemberName.CompareTo(kpOther.Name);
} }
#if !KeePassLibSD #if (!KeePassLibSD && !KeePassRT)
private static readonly Type[] m_vTextControls = new Type[] { private static readonly Type[] m_vTextControls = new Type[] {
typeof(MenuStrip), typeof(PictureBox), typeof(ListView), typeof(MenuStrip), typeof(PictureBox), typeof(ListView),
typeof(TreeView), typeof(ToolStrip), typeof(WebBrowser), typeof(TreeView), typeof(ToolStrip), typeof(WebBrowser),
@@ -313,8 +306,8 @@ namespace ModernKeePassLib.Translation
if(c is Form) if(c is Form)
{ {
WriteCpiParam(sb, c.ClientSize.Width.ToString()); WriteCpiParam(sb, c.ClientSize.Width.ToString(KpccLayout.m_lclInv));
WriteCpiParam(sb, c.ClientSize.Height.ToString()); WriteCpiParam(sb, c.ClientSize.Height.ToString(KpccLayout.m_lclInv));
} }
else // Normal control else // Normal control
{ {
@@ -402,5 +395,3 @@ namespace ModernKeePassLib.Translation
#endif #endif
} }
} }
#endif

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -17,9 +17,6 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
/* Bert TODO: completely removed for the time being */
#if TODO
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
@@ -69,6 +66,7 @@ namespace ModernKeePassLib.Translation
} }
} }
#if (!KeePassLibSD && !KeePassRT)
private Form m_formEnglish = null; private Form m_formEnglish = null;
[XmlIgnore] [XmlIgnore]
public Form FormEnglish public Form FormEnglish
@@ -77,7 +75,6 @@ namespace ModernKeePassLib.Translation
set { m_formEnglish = value; } set { m_formEnglish = value; }
} }
#if !KeePassLibSD
public void ApplyTo(Form form) public void ApplyTo(Form form)
{ {
Debug.Assert(form != null); if(form == null) throw new ArgumentNullException("form"); Debug.Assert(form != null); if(form == null) throw new ArgumentNullException("form");
@@ -107,5 +104,3 @@ namespace ModernKeePassLib.Translation
#endif #endif
} }
} }
#endif //TODO

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -17,9 +17,6 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
/* BERT TODO: Completely removed for the time being */
#if TODO
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
@@ -69,7 +66,7 @@ namespace ModernKeePassLib.Translation
return dict; return dict;
} }
#if !KeePassLibSD #if (!KeePassLibSD && !KeePassRT)
public void ApplyTo(ToolStripItemCollection tsic) public void ApplyTo(ToolStripItemCollection tsic)
{ {
if(tsic == null) throw new ArgumentNullException("tsic"); if(tsic == null) throw new ArgumentNullException("tsic");
@@ -100,5 +97,3 @@ namespace ModernKeePassLib.Translation
#endif #endif
} }
} }
#endif //TODO

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -17,9 +17,6 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
/* Bert TODO: completely removed for the time being */
#if TODO
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
@@ -156,7 +153,7 @@ namespace ModernKeePassLib.Translation
return new Dictionary<string, string>(); return new Dictionary<string, string>();
} }
#if !KeePassLibSD #if (!KeePassLibSD && !KeePassRT)
public void ApplyTo(Form form) public void ApplyTo(Form form)
{ {
if(form == null) throw new ArgumentNullException("form"); if(form == null) throw new ArgumentNullException("form");
@@ -253,5 +250,3 @@ namespace ModernKeePassLib.Translation
#endif #endif
} }
} }
#endif

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -49,9 +49,9 @@ namespace ModernKeePassLib.Utility
try try
{ {
string strDirSep = string.Empty; string strDirSep = string.Empty;
strDirSep += Path.DirectorySeparatorChar; strDirSep += UrlUtil.LocalDirSepChar;
string strTemp = Path.GetTempPath(); string strTemp = UrlUtil.GetTempPath();
if(!strTemp.EndsWith(strDirSep)) if(!strTemp.EndsWith(strDirSep))
strTemp += strDirSep; strTemp += strDirSep;
@@ -64,7 +64,7 @@ namespace ModernKeePassLib.Utility
strTime = strTime.Replace(':', '-'); strTime = strTime.Replace(':', '-');
strPath += strTime + "-" + Environment.TickCount.ToString( strPath += strTime + "-" + Environment.TickCount.ToString(
CultureInfo.InvariantCulture) + ".log.gz"; NumberFormatInfo.InvariantInfo) + ".log.gz";
FileStream fsOut = new FileStream(strPath, FileMode.Create, FileStream fsOut = new FileStream(strPath, FileMode.Create,
FileAccess.Write, FileShare.None); FileAccess.Write, FileShare.None);
@@ -81,12 +81,8 @@ namespace ModernKeePassLib.Utility
{ {
if(m_swOut == null) return; if(m_swOut == null) return;
Debug.Assert(false, "not yet implemented"); m_swOut.Dispose();
return;
#if TODO
m_swOut.Close();
m_swOut = null; m_swOut = null;
#endif
} }
public static void Log(string strText) public static void Log(string strText)

View File

@@ -0,0 +1,57 @@
using System;
using System.Drawing;
using System.Globalization;
using System.Text.RegularExpressions;
namespace KeePass2PCL.Utility
{
/// <summary>
/// Replacement for System.Drawing.ColorTranslator.
/// </summary>
/// <remarks>
/// Colors are stored in the kdbx database file in HTML format (#XXXXXX).
/// </remarks>
public static class ColorTranslator
{
static Regex longForm = new Regex("^#([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})$");
/// <summary>
/// Converts an HTML color value to a Color.
/// </summary>
/// <returns>The Color.</returns>
/// <param name="htmlColor">HTML color code.</param>
/// <exception cref="ArgumentNullException">If htmlColor is null.</exception>
/// <exception cref="ArgumentException">If htmlColor did not match the pattern "#XXXXXX".</exception>
/// <remarks>
/// Currently only understands "#XXXXXX". "#XXX" or named colors will
/// throw and exception.
/// </remarks>
public static Color FromHtml(string htmlColor)
{
if (htmlColor == null)
throw new ArgumentNullException("htmlColor");
Match match = longForm.Match(htmlColor);
if (match.Success) {
var r = int.Parse(match.Groups[1].Value, NumberStyles.HexNumber);
var g = int.Parse(match.Groups[2].Value, NumberStyles.HexNumber);
var b = int.Parse(match.Groups[3].Value, NumberStyles.HexNumber);
return Color.FromArgb(r, g, b);
}
throw new ArgumentException(string.Format("Could not parse HTML color '{0}'.", htmlColor), "htmlColor");
}
/// <summary>
/// Converts a color to an HTML color code.
/// </summary>
/// <returns>String containing the color code.</returns>
/// <param name="htmlColor">The Color to convert</param>
/// <remarks>
/// The string is in the format "#XXXXXX"
/// </remarks>
public static string ToHtml(Color htmlColor)
{
return string.Format("#{0:x2}{1:x2}{2:x2}", htmlColor.R, htmlColor.G, htmlColor.B);
}
}
}

View File

@@ -0,0 +1,115 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
#if KeePass2PCL
using Splat;
#else
using System.Drawing;
using System.Drawing.Imaging;
#endif
using System.Diagnostics;
namespace KeePass2PCL.Utility
{
public static class GfxUtil
{
#if KeePassRT
public static Image LoadImage(byte[] pb)
{
MemoryStream ms = new MemoryStream(pb, false);
try { return Image.FromStream(ms); }
finally { ms.Close(); }
}
#elif KeePass2PCL
public static IBitmap LoadImage(byte[] pb)
{
using (var ms = new MemoryStream(pb, false)) {
return BitmapLoader.Current.Load(ms, null, null).Result;
}
}
#else
public static Image LoadImage(byte[] pb)
{
if(pb == null) throw new ArgumentNullException("pb");
MemoryStream ms = new MemoryStream(pb, false);
try { return LoadImagePriv(ms); }
catch(Exception)
{
Image imgIco = TryLoadIco(pb);
if(imgIco != null) return imgIco;
throw;
}
finally { ms.Close(); }
}
private static Image LoadImagePriv(Stream s)
{
// Image.FromStream wants the stream to be open during
// the whole lifetime of the image; as we can't guarantee
// this, we make a copy of the image
Image imgSrc = null;
try
{
#if !KeePassLibSD
imgSrc = Image.FromStream(s);
Bitmap bmp = new Bitmap(imgSrc.Width, imgSrc.Height,
PixelFormat.Format32bppArgb);
try
{
bmp.SetResolution(imgSrc.HorizontalResolution,
imgSrc.VerticalResolution);
Debug.Assert(bmp.Size == imgSrc.Size);
}
catch(Exception) { Debug.Assert(false); }
#else
imgSrc = new Bitmap(s);
Bitmap bmp = new Bitmap(imgSrc.Width, imgSrc.Height);
#endif
using(Graphics g = Graphics.FromImage(bmp))
{
g.Clear(Color.Transparent);
g.DrawImage(imgSrc, 0, 0);
}
return bmp;
}
finally { if(imgSrc != null) imgSrc.Dispose(); }
}
private static Image TryLoadIco(byte[] pb)
{
#if !KeePassLibSD
MemoryStream ms = new MemoryStream(pb, false);
try { return (new Icon(ms)).ToBitmap(); }
catch(Exception) { }
finally { ms.Close(); }
#endif
return null;
}
#endif
}
}

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -18,21 +18,91 @@
*/ */
using System; using System;
using System.Collections.Generic;
using System.Text; using System.Text;
using System.Diagnostics;
using System.IO; using System.IO;
#if !KeePassLibSD #if !KeePassLibSD
using System.IO.Compression;
#else #else
using ModernKeePassLibSD; using KeePassLibSD;
#endif #endif
namespace ModernKeePassLib.Utility namespace ModernKeePassLib.Utility
{ {
/// <summary> /// <summary>
/// Contains static buffer manipulation and string conversion routines. /// Contains static buffer manipulation and string conversion routines.
/// </summary> /// </summary>
public static class MemUtil public static class MemUtil
{ {
private static readonly uint[] m_vSBox = new uint[256] {
0xCD2FACB3, 0xE78A7F5C, 0x6F0803FC, 0xBCF6E230,
0x3A321712, 0x06403DB1, 0xD2F84B95, 0xDF22A6E4,
0x07CE9E5B, 0x31788A0C, 0xF683F6F4, 0xEA061F49,
0xFA5C2ACA, 0x4B9E494E, 0xB0AB25BA, 0x767731FC,
0x261893A7, 0x2B09F2CE, 0x046261E4, 0x41367B4B,
0x18A7F225, 0x8F923C0E, 0x5EF3A325, 0x28D0435E,
0x84C22919, 0xED66873C, 0x8CEDE444, 0x7FC47C24,
0xFCFC6BA3, 0x676F928D, 0xB4147187, 0xD8FB126E,
0x7D798D17, 0xFF82E424, 0x1712FA5B, 0xABB09DD5,
0x8156BA63, 0x84E4D969, 0xC937FB9A, 0x2F1E5BFC,
0x178ECA11, 0x0E71CD5F, 0x52AAC6F4, 0x71EEFC8F,
0x7090D749, 0x21CACA31, 0x92996378, 0x0939A8A8,
0xE9EE1934, 0xD2718616, 0xF2500543, 0xB911873C,
0xD3CB3EEC, 0x2BA0DBEB, 0xB42D0A27, 0xECE67C0F,
0x302925F0, 0x6114F839, 0xD39E6307, 0xE28970D6,
0xEB982F99, 0x941B4CDF, 0xC540E550, 0x8124FC45,
0x98B025C7, 0xE2BF90EA, 0x4F57C976, 0xCF546FE4,
0x59566DC8, 0xE3F4360D, 0xF5F9D231, 0xD6180B22,
0xB54E088A, 0xB5DFE6A6, 0x3637A36F, 0x056E9284,
0xAFF8FBC5, 0x19E01648, 0x8611F043, 0xDAE44337,
0xF61B6A1C, 0x257ACD9E, 0xDD35F507, 0xEF05CAFA,
0x05EB4A83, 0xFC25CA92, 0x0A4728E6, 0x9CF150EF,
0xAEEF67DE, 0xA9472337, 0x57C81EFE, 0x3E5E009F,
0x02CB03BB, 0x2BA85674, 0xF21DC251, 0x78C34A34,
0xABB1F5BF, 0xB95A2FBD, 0x1FB47777, 0x9A96E8AC,
0x5D2D2838, 0x55AAC92A, 0x99EE324E, 0x10F6214B,
0x58ABDFB1, 0x2008794D, 0xBEC880F0, 0xE75E5341,
0x88015C34, 0x352D8FBF, 0x622B7F6C, 0xF5C59EA2,
0x1F759D8E, 0xADE56159, 0xCC7B4C25, 0x5B8BC48C,
0xB6BD15AF, 0x3C5B5110, 0xE74A7C3D, 0xEE613161,
0x156A1C67, 0x72C06817, 0xEA0A6F69, 0x4CECF993,
0xCA9D554C, 0x8E20361F, 0x42D396B9, 0x595DE578,
0x749D7955, 0xFD1BA5FD, 0x81FC160E, 0xDB97E28C,
0x7CF148F7, 0x0B0B3CF5, 0x534DE605, 0x46421066,
0xD4B68DD1, 0x9E479CE6, 0xAE667A9D, 0xBC082082,
0xB06DD6EF, 0x20F0F23F, 0xB99E1551, 0xF47A2E3A,
0x71DA50C6, 0x67B65779, 0x2A8CB376, 0x1EA71EEE,
0x29ABCD50, 0xB6EB0C6B, 0x23C10511, 0x6F3F2144,
0x6AF23012, 0xF696BD9E, 0xB94099D8, 0xAD5A9C81,
0x7A0794FA, 0x7EDF59D6, 0x1E72E574, 0x8561913C,
0x4E4D568F, 0xEECB9928, 0x9C124D2E, 0x0848B82C,
0xF1CA395F, 0x9DAF43DC, 0xF77EC323, 0x394E9B59,
0x7E200946, 0x8B811D68, 0x16DA3305, 0xAB8DE2C3,
0xE6C53B64, 0x98C2D321, 0x88A97D81, 0xA7106419,
0x8E52F7BF, 0x8ED262AF, 0x7CCA974E, 0xF0933241,
0x040DD437, 0xE143B3D4, 0x3019F56F, 0xB741521D,
0xF1745362, 0x4C435F9F, 0xB4214D0D, 0x0B0C348B,
0x5051D189, 0x4C30447E, 0x7393D722, 0x95CEDD0B,
0xDD994E80, 0xC3D22ED9, 0x739CD900, 0x131EB9C4,
0xEF1062B2, 0x4F0DE436, 0x52920073, 0x9A7F3D80,
0x896E7B1B, 0x2C8BBE5A, 0xBD304F8A, 0xA993E22C,
0x134C41A0, 0xFA989E00, 0x39CE9726, 0xFB89FCCF,
0xE8FBAC97, 0xD4063FFC, 0x935A2B5A, 0x44C8EE83,
0xCB2BC7B6, 0x02989E92, 0x75478BEA, 0x144378D0,
0xD853C087, 0x8897A34E, 0xDD23629D, 0xBDE2A2A2,
0x581D8ECC, 0x5DA8AEE8, 0xFF8AAFD0, 0xBA2BCF6E,
0x4BD98DAC, 0xF2EDB9E4, 0xFA2DC868, 0x47E84661,
0xECEB1C7D, 0x41705CA4, 0x5982E4D4, 0xEB5204A1,
0xD196CAFB, 0x6414804D, 0x3ABD4B46, 0x8B494C26,
0xB432D52B, 0x39C5356B, 0x6EC80BF7, 0x71BE5483,
0xCEC4A509, 0xE9411D61, 0x52F341E5, 0xD2E6197B,
0x4F02826C, 0xA9E48838, 0xD1F8F247, 0xE4957FB3,
0x586CCA99, 0x9A8B6A5B, 0x4998FBEA, 0xF762BE4C,
0x90DFE33C, 0x9731511E, 0x88C6A82F, 0xDD65A4D4
};
/// <summary> /// <summary>
/// Convert a hexadecimal string to a byte array. The input string must be /// Convert a hexadecimal string to a byte array. The input string must be
/// even (i.e. its length is a multiple of 2). /// even (i.e. its length is a multiple of 2).
@@ -116,6 +186,63 @@ namespace ModernKeePassLib.Utility
return sb.ToString(); return sb.ToString();
} }
/// <summary>
/// Decode Base32 strings according to RFC 4648.
/// </summary>
public static byte[] ParseBase32(string str)
{
if((str == null) || ((str.Length % 8) != 0))
{
Debug.Assert(false);
return null;
}
ulong uMaxBits = (ulong)str.Length * 5UL;
List<byte> l = new List<byte>((int)(uMaxBits / 8UL) + 1);
Debug.Assert(l.Count == 0);
for(int i = 0; i < str.Length; i += 8)
{
ulong u = 0;
int nBits = 0;
for(int j = 0; j < 8; ++j)
{
char ch = str[i + j];
if(ch == '=') break;
ulong uValue;
if((ch >= 'A') && (ch <= 'Z'))
uValue = (ulong)(ch - 'A');
else if((ch >= 'a') && (ch <= 'z'))
uValue = (ulong)(ch - 'a');
else if((ch >= '2') && (ch <= '7'))
uValue = (ulong)(ch - '2') + 26UL;
else { Debug.Assert(false); return null; }
u <<= 5;
u += uValue;
nBits += 5;
}
int nBitsTooMany = (nBits % 8);
u >>= nBitsTooMany;
nBits -= nBitsTooMany;
Debug.Assert((nBits % 8) == 0);
int idxNewBytes = l.Count;
while(nBits > 0)
{
l.Add((byte)(u & 0xFF));
u >>= 8;
nBits -= 8;
}
l.Reverse(idxNewBytes, l.Count - idxNewBytes);
}
return l.ToArray();
}
/// <summary> /// <summary>
/// Set all bytes in a byte array to zero. /// Set all bytes in a byte array to zero.
/// </summary> /// </summary>
@@ -123,7 +250,8 @@ namespace ModernKeePassLib.Utility
/// to zero.</param> /// to zero.</param>
public static void ZeroByteArray(byte[] pbArray) public static void ZeroByteArray(byte[] pbArray)
{ {
Debug.Assert(pbArray != null); if(pbArray == null) throw new ArgumentNullException("pbArray"); Debug.Assert(pbArray != null);
if(pbArray == null) throw new ArgumentNullException("pbArray");
// for(int i = 0; i < pbArray.Length; ++i) // for(int i = 0; i < pbArray.Length; ++i)
// pbArray[i] = 0; // pbArray[i] = 0;
@@ -274,6 +402,31 @@ namespace ModernKeePassLib.Utility
pbBuffer[nBufferOffset + i] ^= pbSource[nSourceOffset + i]; pbBuffer[nBufferOffset + i] ^= pbSource[nSourceOffset + i];
} }
/// <summary>
/// Fast hash that can be used e.g. for hash tables.
/// The algorithm might change in the future; do not store
/// the hashes for later use.
/// </summary>
public static uint Hash32(byte[] v, int iStart, int iLength)
{
uint u = 0x326F637B;
if(v == null) { Debug.Assert(false); return u; }
if(iStart < 0) { Debug.Assert(false); return u; }
if(iLength < 0) { Debug.Assert(false); return u; }
int m = iStart + iLength;
if(m > v.Length) { Debug.Assert(false); return u; }
for(int i = iStart; i < m; ++i)
{
u ^= m_vSBox[v[i]];
u *= 3;
}
return u;
}
public static void CopyStream(Stream sSource, Stream sTarget) public static void CopyStream(Stream sSource, Stream sTarget)
{ {
Debug.Assert((sSource != null) && (sTarget != null)); Debug.Assert((sSource != null) && (sTarget != null));
@@ -282,19 +435,54 @@ namespace ModernKeePassLib.Utility
const int nBufSize = 4096; const int nBufSize = 4096;
byte[] pbBuf = new byte[nBufSize]; byte[] pbBuf = new byte[nBufSize];
int nRead;
while((nRead = sSource.Read(pbBuf, 0, nBufSize)) > 0) while(true)
{
int nRead = sSource.Read(pbBuf, 0, nBufSize);
if(nRead == 0) break;
sTarget.Write(pbBuf, 0, nRead); sTarget.Write(pbBuf, 0, nRead);
}
// Do not close any of the streams // Do not close any of the streams
} }
public static byte[] Read(Stream s, int nCount)
{
if(s == null) throw new ArgumentNullException("s");
if(nCount < 0) throw new ArgumentOutOfRangeException("nCount");
byte[] pb = new byte[nCount];
int iOffset = 0;
while(nCount > 0)
{
int iRead = s.Read(pb, iOffset, nCount);
if(iRead == 0) break;
iOffset += iRead;
nCount -= iRead;
}
if(iOffset != pb.Length)
{
byte[] pbPart = new byte[iOffset];
Array.Copy(pb, pbPart, iOffset);
return pbPart;
}
return pb;
}
public static void Write(Stream s, byte[] pbData)
{
if(s == null) { Debug.Assert(false); return; }
if(pbData == null) { Debug.Assert(false); return; }
s.Write(pbData, 0, pbData.Length);
}
public static byte[] Compress(byte[] pbData) public static byte[] Compress(byte[] pbData)
{ {
Debug.Assert(false, "not yet implemented");
return null;
#if TODO
if(pbData == null) throw new ArgumentNullException("pbData"); if(pbData == null) throw new ArgumentNullException("pbData");
if(pbData.Length == 0) return pbData; if(pbData.Length == 0) return pbData;
@@ -302,20 +490,16 @@ namespace ModernKeePassLib.Utility
GZipStream gz = new GZipStream(msCompressed, CompressionMode.Compress); GZipStream gz = new GZipStream(msCompressed, CompressionMode.Compress);
MemoryStream msSource = new MemoryStream(pbData, false); MemoryStream msSource = new MemoryStream(pbData, false);
MemUtil.CopyStream(msSource, gz); MemUtil.CopyStream(msSource, gz);
gz.Close(); gz.Dispose();
msSource.Close(); msSource.Dispose();
byte[] pbCompressed = msCompressed.ToArray(); byte[] pbCompressed = msCompressed.ToArray();
msCompressed.Close(); msCompressed.Dispose();
return pbCompressed; return pbCompressed;
#endif
} }
public static byte[] Decompress(byte[] pbCompressed) public static byte[] Decompress(byte[] pbCompressed)
{ {
Debug.Assert(false, "not yet implemented");
return null;
#if TODO
if(pbCompressed == null) throw new ArgumentNullException("pbCompressed"); if(pbCompressed == null) throw new ArgumentNullException("pbCompressed");
if(pbCompressed.Length == 0) return pbCompressed; if(pbCompressed.Length == 0) return pbCompressed;
@@ -323,13 +507,12 @@ namespace ModernKeePassLib.Utility
GZipStream gz = new GZipStream(msCompressed, CompressionMode.Decompress); GZipStream gz = new GZipStream(msCompressed, CompressionMode.Decompress);
MemoryStream msData = new MemoryStream(); MemoryStream msData = new MemoryStream();
MemUtil.CopyStream(gz, msData); MemUtil.CopyStream(gz, msData);
gz.Close(); gz.Dispose();
msCompressed.Close(); msCompressed.Dispose();
byte[] pbData = msData.ToArray(); byte[] pbData = msData.ToArray();
msData.Close(); msData.Dispose();
return pbData; return pbData;
#endif
} }
public static int IndexOf<T>(T[] vHaystack, T[] vNeedle) public static int IndexOf<T>(T[] vHaystack, T[] vNeedle)
@@ -361,11 +544,81 @@ namespace ModernKeePassLib.Utility
if(v == null) throw new ArgumentNullException("v"); if(v == null) throw new ArgumentNullException("v");
if(iOffset < 0) throw new ArgumentOutOfRangeException("iOffset"); if(iOffset < 0) throw new ArgumentOutOfRangeException("iOffset");
if(iLength < 0) throw new ArgumentOutOfRangeException("iLength"); if(iLength < 0) throw new ArgumentOutOfRangeException("iLength");
if(iOffset + iLength > v.Length) throw new ArgumentException(); if((iOffset + iLength) > v.Length) throw new ArgumentException();
T[] r = new T[iLength]; T[] r = new T[iLength];
Array.Copy(v, iOffset, r, 0, iLength); Array.Copy(v, iOffset, r, 0, iLength);
return r; return r;
} }
public static IEnumerable<T> Union<T>(IEnumerable<T> a, IEnumerable<T> b,
IEqualityComparer<T> cmp)
{
if(a == null) throw new ArgumentNullException("a");
if(b == null) throw new ArgumentNullException("b");
Dictionary<T, bool> d = ((cmp != null) ?
(new Dictionary<T, bool>(cmp)) : (new Dictionary<T, bool>()));
foreach(T ta in a)
{
if(d.ContainsKey(ta)) continue; // Prevent duplicates
d[ta] = true;
yield return ta;
}
foreach(T tb in b)
{
if(d.ContainsKey(tb)) continue; // Prevent duplicates
d[tb] = true;
yield return tb;
}
yield break;
}
public static IEnumerable<T> Intersect<T>(IEnumerable<T> a, IEnumerable<T> b,
IEqualityComparer<T> cmp)
{
if(a == null) throw new ArgumentNullException("a");
if(b == null) throw new ArgumentNullException("b");
Dictionary<T, bool> d = ((cmp != null) ?
(new Dictionary<T, bool>(cmp)) : (new Dictionary<T, bool>()));
foreach(T tb in b) { d[tb] = true; }
foreach(T ta in a)
{
if(d.Remove(ta)) // Prevent duplicates
yield return ta;
}
yield break;
}
public static IEnumerable<T> Except<T>(IEnumerable<T> a, IEnumerable<T> b,
IEqualityComparer<T> cmp)
{
if(a == null) throw new ArgumentNullException("a");
if(b == null) throw new ArgumentNullException("b");
Dictionary<T, bool> d = ((cmp != null) ?
(new Dictionary<T, bool>(cmp)) : (new Dictionary<T, bool>()));
foreach(T tb in b) { d[tb] = true; }
foreach(T ta in a)
{
if(d.ContainsKey(ta)) continue;
d[ta] = true; // Prevent duplicates
yield return ta;
}
yield break;
}
} }
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -17,9 +17,6 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
/* BERT TODO: All removed for the time being */
#if false
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
@@ -121,7 +118,7 @@ namespace ModernKeePassLib.Utility
Exception exObj = (obj as Exception); Exception exObj = (obj as Exception);
string strObj = (obj as string); string strObj = (obj as string);
#if !KeePassLibSD #if (!KeePassLibSD && !KeePassRT)
StringCollection scObj = (obj as StringCollection); StringCollection scObj = (obj as StringCollection);
#endif #endif
@@ -132,7 +129,7 @@ namespace ModernKeePassLib.Utility
else if((exObj.Message != null) && (exObj.Message.Length > 0)) else if((exObj.Message != null) && (exObj.Message.Length > 0))
strAppend = exObj.Message; strAppend = exObj.Message;
} }
#if !KeePassLibSD #if (!KeePassLibSD && !KeePassRT)
else if(scObj != null) else if(scObj != null)
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@@ -161,24 +158,30 @@ namespace ModernKeePassLib.Utility
return sbText.ToString(); return sbText.ToString();
} }
private static DialogResult SafeShowMessageBox(string strText, string strTitle, #if (!KeePassLibSD && !KeePassRT)
internal static Form GetTopForm()
{
FormCollection fc = Application.OpenForms;
if((fc == null) || (fc.Count == 0)) return null;
return fc[fc.Count - 1];
}
#endif
internal static DialogResult SafeShowMessageBox(string strText, string strTitle,
MessageBoxButtons mb, MessageBoxIcon mi, MessageBoxDefaultButton mdb) MessageBoxButtons mb, MessageBoxIcon mi, MessageBoxDefaultButton mdb)
{ {
#if KeePassLibSD #if (KeePassLibSD || KeePassRT)
return MessageBox.Show(strText, strTitle, mb, mi, mdb); return MessageBox.Show(strText, strTitle, mb, mi, mdb);
#else #else
IWin32Window wnd = null; IWin32Window wnd = null;
try try
{ {
FormCollection fc = Application.OpenForms; Form f = GetTopForm();
if((fc != null) && (fc.Count > 0)) if((f != null) && f.InvokeRequired)
{ return (DialogResult)f.Invoke(new SafeShowMessageBoxInternalDelegate(
Form f = fc[fc.Count - 1]; SafeShowMessageBoxInternal), f, strText, strTitle, mb, mi, mdb);
if((f != null) && f.InvokeRequired) else wnd = f;
return (DialogResult)f.Invoke(new SafeShowMessageBoxInternalDelegate(
SafeShowMessageBoxInternal), f, strText, strTitle, mb, mi, mdb);
else wnd = f;
}
} }
catch(Exception) { Debug.Assert(false); } catch(Exception) { Debug.Assert(false); }
@@ -203,7 +206,7 @@ namespace ModernKeePassLib.Utility
#endif #endif
} }
#if !KeePassLibSD #if (!KeePassLibSD && !KeePassRT)
internal delegate DialogResult SafeShowMessageBoxInternalDelegate(IWin32Window iParent, internal delegate DialogResult SafeShowMessageBoxInternalDelegate(IWin32Window iParent,
string strText, string strTitle, MessageBoxButtons mb, MessageBoxIcon mi, string strText, string strTitle, MessageBoxButtons mb, MessageBoxIcon mi,
MessageBoxDefaultButton mdb); MessageBoxDefaultButton mdb);
@@ -318,7 +321,8 @@ namespace ModernKeePassLib.Utility
return dr; return dr;
} }
public static bool AskYesNo(string strText, string strTitle, bool bDefaultToYes) public static bool AskYesNo(string strText, string strTitle, bool bDefaultToYes,
MessageBoxIcon mbi)
{ {
++m_uCurrentMessageCount; ++m_uCurrentMessageCount;
@@ -327,24 +331,29 @@ namespace ModernKeePassLib.Utility
if(MessageService.MessageShowing != null) if(MessageService.MessageShowing != null)
MessageService.MessageShowing(null, new MessageServiceEventArgs( MessageService.MessageShowing(null, new MessageServiceEventArgs(
strTitleEx, strTextEx, MessageBoxButtons.YesNo, m_mbiQuestion)); strTitleEx, strTextEx, MessageBoxButtons.YesNo, mbi));
DialogResult dr = SafeShowMessageBox(strTextEx, strTitleEx, DialogResult dr = SafeShowMessageBox(strTextEx, strTitleEx,
MessageBoxButtons.YesNo, m_mbiQuestion, bDefaultToYes ? MessageBoxButtons.YesNo, mbi, bDefaultToYes ?
MessageBoxDefaultButton.Button1 : MessageBoxDefaultButton.Button2); MessageBoxDefaultButton.Button1 : MessageBoxDefaultButton.Button2);
--m_uCurrentMessageCount; --m_uCurrentMessageCount;
return (dr == DialogResult.Yes); return (dr == DialogResult.Yes);
} }
public static bool AskYesNo(string strText, string strTitle, bool bDefaultToYes)
{
return AskYesNo(strText, strTitle, bDefaultToYes, m_mbiQuestion);
}
public static bool AskYesNo(string strText, string strTitle) public static bool AskYesNo(string strText, string strTitle)
{ {
return AskYesNo(strText, strTitle, true); return AskYesNo(strText, strTitle, true, m_mbiQuestion);
} }
public static bool AskYesNo(string strText) public static bool AskYesNo(string strText)
{ {
return AskYesNo(strText, null, true); return AskYesNo(strText, null, true, m_mbiQuestion);
} }
public static void ShowLoadWarning(string strFilePath, Exception ex) public static void ShowLoadWarning(string strFilePath, Exception ex)
@@ -423,5 +432,3 @@ namespace ModernKeePassLib.Utility
} }
} }
} }
#endif // false

View File

@@ -0,0 +1,324 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
using System.Reflection;
using System.Diagnostics;
using KeePass2PCL.Native;
namespace KeePass2PCL.Utility
{
public static class MonoWorkarounds
{
private static bool? m_bReq = null;
public static bool IsRequired()
{
if(!m_bReq.HasValue) m_bReq = NativeLib.IsUnix();
return m_bReq.Value;
}
// 1245:
// Key events not raised while Alt is down, and nav keys out of order.
// https://sourceforge.net/p/keepass/bugs/1245/
// 1254:
// NumericUpDown bug: text is drawn below up/down buttons.
// https://sourceforge.net/p/keepass/bugs/1254/
// 5795:
// Text in input field is incomplete.
// https://bugzilla.xamarin.com/show_bug.cgi?id=5795
// https://sourceforge.net/p/keepass/discussion/329220/thread/d23dc88b/
// 10163:
// WebRequest GetResponse call missing, breaks WebDAV due to no PUT.
// https://bugzilla.xamarin.com/show_bug.cgi?id=10163
// https://sourceforge.net/p/keepass/bugs/1117/
// https://sourceforge.net/p/keepass/discussion/329221/thread/9422258c/
// https://github.com/mono/mono/commit/8e67b8c2fc7cb66bff7816ebf7c1039fb8cfc43b
// https://bugzilla.xamarin.com/show_bug.cgi?id=1512
// https://sourceforge.net/p/keepass/patches/89/
// 12525:
// PictureBox not rendered when bitmap height >= control height.
// https://bugzilla.xamarin.com/show_bug.cgi?id=12525
// https://sourceforge.net/p/keepass/discussion/329220/thread/54f61e9a/
// 586901:
// RichTextBox doesn't handle Unicode string correctly.
// https://bugzilla.novell.com/show_bug.cgi?id=586901
// 620618:
// ListView column headers not drawn.
// https://bugzilla.novell.com/show_bug.cgi?id=620618
// 649266:
// Calling Control.Hide doesn't remove the application from taskbar.
// https://bugzilla.novell.com/show_bug.cgi?id=649266
// 686017:
// Minimum sizes must be enforced.
// http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=686017
// 801414:
// Mono recreates the main window incorrectly.
// https://bugs.launchpad.net/ubuntu/+source/keepass2/+bug/801414
// 891029:
// Increase tab control height, otherwise Mono throws exceptions.
// https://sourceforge.net/projects/keepass/forums/forum/329221/topic/4519750
// https://bugs.launchpad.net/ubuntu/+source/keepass2/+bug/891029
// 836428016:
// ListView group header selection unsupported.
// https://sourceforge.net/p/keepass/discussion/329221/thread/31dae0f0/
// 3574233558:
// Problems with minimizing windows, no content rendered.
// https://sourceforge.net/p/keepass/discussion/329220/thread/d50a79d6/
public static bool IsRequired(uint uBugID)
{
if(!MonoWorkarounds.IsRequired()) return false;
ulong v = NativeLib.MonoVersion;
if(v != 0)
{
if(uBugID == 10163)
return (v >= 0x0002000B00000000UL); // >= 2.11
}
return true;
}
public static void ApplyTo(Form f)
{
if(!MonoWorkarounds.IsRequired()) return;
if(f == null) { Debug.Assert(false); return; }
#if (!KeePassLibSD && !KeePassRT)
f.HandleCreated += MonoWorkarounds.OnFormHandleCreated;
SetWmClass(f);
ApplyToControlsRec(f.Controls, f, MonoWorkarounds.ApplyToControl);
#endif
}
public static void Release(Form f)
{
if(!MonoWorkarounds.IsRequired()) return;
if(f == null) { Debug.Assert(false); return; }
#if (!KeePassLibSD && !KeePassRT)
f.HandleCreated -= MonoWorkarounds.OnFormHandleCreated;
ApplyToControlsRec(f.Controls, f, MonoWorkarounds.ReleaseControl);
#endif
}
#if (!KeePassLibSD && !KeePassRT)
private delegate void MwaControlHandler(Control c, Form fContext);
private static void ApplyToControlsRec(Control.ControlCollection cc,
Form fContext, MwaControlHandler fn)
{
if(cc == null) { Debug.Assert(false); return; }
foreach(Control c in cc)
{
fn(c, fContext);
ApplyToControlsRec(c.Controls, fContext, fn);
}
}
private static void ApplyToControl(Control c, Form fContext)
{
Button btn = (c as Button);
if(btn != null) ApplyToButton(btn, fContext);
NumericUpDown nc = (c as NumericUpDown);
if((nc != null) && MonoWorkarounds.IsRequired(1254))
{
if(nc.TextAlign == HorizontalAlignment.Right)
nc.TextAlign = HorizontalAlignment.Left;
}
}
private sealed class MwaHandlerInfo
{
private readonly Delegate m_fnOrg; // May be null
public Delegate FunctionOriginal
{
get { return m_fnOrg; }
}
private readonly Delegate m_fnOvr;
public Delegate FunctionOverride
{
get { return m_fnOvr; }
}
private readonly DialogResult m_dr;
public DialogResult Result
{
get { return m_dr; }
}
private readonly Form m_fContext;
public Form FormContext
{
get { return m_fContext; }
}
public MwaHandlerInfo(Delegate fnOrg, Delegate fnOvr, DialogResult dr,
Form fContext)
{
m_fnOrg = fnOrg;
m_fnOvr = fnOvr;
m_dr = dr;
m_fContext = fContext;
}
}
private static EventHandlerList GetEventHandlers(Component c,
out object objClickEvent)
{
FieldInfo fi = typeof(Control).GetField("ClickEvent", // Mono
BindingFlags.Static | BindingFlags.NonPublic);
if(fi == null)
fi = typeof(Control).GetField("EventClick", // .NET
BindingFlags.Static | BindingFlags.NonPublic);
if(fi == null) { Debug.Assert(false); objClickEvent = null; return null; }
objClickEvent = fi.GetValue(null);
if(objClickEvent == null) { Debug.Assert(false); return null; }
PropertyInfo pi = typeof(Component).GetProperty("Events",
BindingFlags.Instance | BindingFlags.NonPublic);
return (pi.GetValue(c, null) as EventHandlerList);
}
private static Dictionary<object, MwaHandlerInfo> m_dictHandlers =
new Dictionary<object, MwaHandlerInfo>();
private static void ApplyToButton(Button btn, Form fContext)
{
DialogResult dr = btn.DialogResult;
if(dr == DialogResult.None) return; // No workaround required
object objClickEvent;
EventHandlerList ehl = GetEventHandlers(btn, out objClickEvent);
if(ehl == null) { Debug.Assert(false); return; }
Delegate fnClick = ehl[objClickEvent]; // May be null
EventHandler fnOvr = new EventHandler(MonoWorkarounds.OnButtonClick);
m_dictHandlers[btn] = new MwaHandlerInfo(fnClick, fnOvr, dr, fContext);
btn.DialogResult = DialogResult.None;
if(fnClick != null) ehl.RemoveHandler(objClickEvent, fnClick);
ehl[objClickEvent] = fnOvr;
}
private static void ReleaseControl(Control c, Form fContext)
{
Button btn = (c as Button);
if(btn != null) ReleaseButton(btn, fContext);
}
private static void ReleaseButton(Button btn, Form fContext)
{
MwaHandlerInfo hi;
m_dictHandlers.TryGetValue(btn, out hi);
if(hi == null) return;
object objClickEvent;
EventHandlerList ehl = GetEventHandlers(btn, out objClickEvent);
if(ehl == null) { Debug.Assert(false); return; }
ehl.RemoveHandler(objClickEvent, hi.FunctionOverride);
if(hi.FunctionOriginal != null)
ehl[objClickEvent] = hi.FunctionOriginal;
btn.DialogResult = hi.Result;
m_dictHandlers.Remove(btn);
}
private static void OnButtonClick(object sender, EventArgs e)
{
Button btn = (sender as Button);
if(btn == null) { Debug.Assert(false); return; }
MwaHandlerInfo hi;
m_dictHandlers.TryGetValue(btn, out hi);
if(hi == null) { Debug.Assert(false); return; }
Form f = hi.FormContext;
// Set current dialog result by setting the form's private
// variable; the DialogResult property can't be used,
// because it raises close events
FieldInfo fiRes = typeof(Form).GetField("dialog_result",
BindingFlags.Instance | BindingFlags.NonPublic);
if(fiRes == null) { Debug.Assert(false); return; }
if(f != null) fiRes.SetValue(f, hi.Result);
if(hi.FunctionOriginal != null)
hi.FunctionOriginal.Method.Invoke(hi.FunctionOriginal.Target,
new object[] { btn, e });
// Raise close events, if the click event handler hasn't
// reset the dialog result
if((f != null) && (f.DialogResult == hi.Result))
f.DialogResult = hi.Result; // Raises close events
}
private static void SetWmClass(Form f)
{
NativeMethods.SetWmClass(f, PwDefs.UnixName, PwDefs.ResClass);
}
private static void OnFormHandleCreated(object sender, EventArgs e)
{
Form f = (sender as Form);
if(f == null) { Debug.Assert(false); return; }
if(!f.IsHandleCreated) return; // Prevent infinite loop
SetWmClass(f);
}
/// <summary>
/// Set the value of the private <c>shown_raised</c> member
/// variable of a form.
/// </summary>
/// <returns>Previous <c>shown_raised</c> value.</returns>
internal static bool ExchangeFormShownRaised(Form f, bool bNewValue)
{
if(f == null) { Debug.Assert(false); return true; }
try
{
FieldInfo fi = typeof(Form).GetField("shown_raised",
BindingFlags.Instance | BindingFlags.NonPublic);
if(fi == null) { Debug.Assert(false); return true; }
bool bPrevious = (bool)fi.GetValue(f);
fi.SetValue(f, bNewValue);
return bPrevious;
}
catch(Exception) { Debug.Assert(false); }
return true;
}
#endif
}
}

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -18,22 +18,34 @@
*/ */
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
//using System.Drawing;
using ModernKeePassLib.WinRTAdaptors;
using System.IO; using System.IO;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
#if PCL
using Windows.Security.Cryptography;
#else
using System.Security.Cryptography;
#endif
using System.Globalization;
using System.Diagnostics;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Security.Cryptography.DataProtection;
using Windows.Storage.Streams;
using Windows.UI;
using ModernKeePassLib.Collections; using ModernKeePassLib.Collections;
using ModernKeePassLib.Cryptography.PasswordGenerator;
using ModernKeePassLib.Security; using ModernKeePassLib.Security;
using ModernKeePassLib.Resources;
using UnicodeEncoding = System.Text.UnicodeEncoding;
namespace ModernKeePassLib.Utility namespace ModernKeePassLib.Utility
{ {
/// <summary> /// <summary>
/// Character stream class. /// Character stream class.
/// </summary> /// </summary>
public sealed class CharStream public sealed class CharStream
{ {
private string m_strString = string.Empty; private string m_strString = string.Empty;
private int m_nPos = 0; private int m_nPos = 0;
@@ -208,53 +220,47 @@ namespace ModernKeePassLib.Utility
{ {
get get
{ {
if(m_lEncs == null) if(m_lEncs != null) return m_lEncs;
{
m_lEncs = new List<StrEncodingInfo>();
#if !KeePassWinRT
m_lEncs.Add(new StrEncodingInfo(StrEncodingType.Default,
List<StrEncodingInfo> l = new List<StrEncodingInfo>();
#if !KeePassLibSD l.Add(new StrEncodingInfo(StrEncodingType.Default,
Encoding.Default.EncodingName, #if PCL || KeePassRT
StrUtil.Utf8.WebName, StrUtil.Utf8, 1, null));
#else #else
Encoding.Default.WebName,
#endif
Encoding.Default,
(uint)Encoding.Default.GetBytes("a").Length, null));
m_lEncs.Add(new StrEncodingInfo(StrEncodingType.Ascii,
"ASCII", Encoding.ASCII, 1, null));
m_lEncs.Add(new StrEncodingInfo(StrEncodingType.Utf7,
"Unicode (UTF-7)", Encoding.UTF7, 1, null));
m_lEncs.Add(new StrEncodingInfo(StrEncodingType.Utf8,
"Unicode (UTF-8)", StrUtil.Utf8, 1, new byte[] { 0xEF, 0xBB, 0xBF }));
m_lEncs.Add(new StrEncodingInfo(StrEncodingType.Utf16LE,
"Unicode (UTF-16 LE)", new UnicodeEncoding(false, false),
2, new byte[] { 0xFF, 0xFE }));
m_lEncs.Add(new StrEncodingInfo(StrEncodingType.Utf16BE,
"Unicode (UTF-16 BE)", new UnicodeEncoding(true, false),
2, new byte[] { 0xFE, 0xFF }));
#if !KeePassLibSD #if !KeePassLibSD
m_lEncs.Add(new StrEncodingInfo(StrEncodingType.Utf32LE, Encoding.Default.EncodingName,
"Unicode (UTF-32 LE)", new UTF32Encoding(false, false), #else
4, new byte[] { 0xFF, 0xFE, 0x0, 0x0 })); Encoding.Default.WebName,
m_lEncs.Add(new StrEncodingInfo(StrEncodingType.Utf32BE,
"Unicode (UTF-32 BE)", new UTF32Encoding(true, false),
4, new byte[] { 0x0, 0x0, 0xFE, 0xFF }));
#endif #endif
#else // KeePassWinRT Encoding.Default,
m_lEncs.Add(new StrEncodingInfo(StrEncodingType.Utf8, (uint)Encoding.Default.GetBytes("a").Length, null));
"Unicode (UTF-8)", StrUtil.Utf8, 1, new byte[] { 0xEF, 0xBB, 0xBF })); #endif
m_lEncs.Add(new StrEncodingInfo(StrEncodingType.Utf16LE, #if !PCL && !KeePassRT
"Unicode (UTF-16 LE)", new UnicodeEncoding(false, false), l.Add(new StrEncodingInfo(StrEncodingType.Ascii,
2, new byte[] { 0xFF, 0xFE })); "ASCII", Encoding.ASCII, 1, null));
m_lEncs.Add(new StrEncodingInfo(StrEncodingType.Utf16BE, l.Add(new StrEncodingInfo(StrEncodingType.Utf7,
"Unicode (UTF-16 BE)", new UnicodeEncoding(true, false), "Unicode (UTF-7)", Encoding.UTF7, 1, null));
2, new byte[] { 0xFE, 0xFF })); #endif
l.Add(new StrEncodingInfo(StrEncodingType.Utf8,
"Unicode (UTF-8)", StrUtil.Utf8, 1, new byte[] { 0xEF, 0xBB, 0xBF }));
l.Add(new StrEncodingInfo(StrEncodingType.Utf16LE,
"Unicode (UTF-16 LE)", new UnicodeEncoding(false, false),
2, new byte[] { 0xFF, 0xFE }));
l.Add(new StrEncodingInfo(StrEncodingType.Utf16BE,
"Unicode (UTF-16 BE)", new UnicodeEncoding(true, false),
2, new byte[] { 0xFE, 0xFF }));
#if (!PCL && !KeePassLibSD && !KeePassRT)
l.Add(new StrEncodingInfo(StrEncodingType.Utf32LE,
"Unicode (UTF-32 LE)", new UTF32Encoding(false, false),
4, new byte[] { 0xFF, 0xFE, 0x0, 0x0 }));
l.Add(new StrEncodingInfo(StrEncodingType.Utf32BE,
"Unicode (UTF-32 BE)", new UTF32Encoding(true, false),
4, new byte[] { 0x0, 0x0, 0xFE, 0xFF }));
#endif #endif
}
return m_lEncs; m_lEncs = l;
return l;
} }
} }
@@ -282,16 +288,21 @@ namespace ModernKeePassLib.Utility
// { // {
// char ch = str[i]; // char ch = str[i];
// if((int)ch >= 256) // if((int)ch >= 256)
// { // sbEncoded.Append(StrUtil.RtfEncodeChar(ch));
// sbEncoded.Append("\\u");
// sbEncoded.Append((int)ch);
// sbEncoded.Append('?');
// }
// else sbEncoded.Append(ch); // else sbEncoded.Append(ch);
// } // }
// return sbEncoded.ToString(); // return sbEncoded.ToString();
// } // }
public static string RtfEncodeChar(char ch)
{
// Unicode character values must be encoded using
// 16-bit numbers (decimal); Unicode values greater
// than 32767 must be expressed as negative numbers
short sh = (short)ch;
return ("\\u" + sh.ToString(NumberFormatInfo.InvariantInfo) + "?");
}
/// <summary> /// <summary>
/// Convert a string into a valid HTML sequence representing that string. /// Convert a string into a valid HTML sequence representing that string.
/// </summary> /// </summary>
@@ -308,7 +319,7 @@ namespace ModernKeePassLib.Utility
str = str.Replace("\'", @"&#39;"); str = str.Replace("\'", @"&#39;");
str = NormalizeNewLines(str, false); str = NormalizeNewLines(str, false);
str = str.Replace("\n", @"<br />"); str = str.Replace("\n", @"<br />" + Environment.NewLine);
return str; return str;
} }
@@ -479,59 +490,59 @@ namespace ModernKeePassLib.Utility
/// <returns>String representing the exception.</returns> /// <returns>String representing the exception.</returns>
public static string FormatException(Exception excp) public static string FormatException(Exception excp)
{ {
Debug.Assert(false, "not yet implemented");
return "";
#if TODO
string strText = string.Empty; string strText = string.Empty;
if(excp.Message != null) if(excp.Message != null)
strText += excp.Message + MessageService.NewLine; strText += excp.Message + Environment.NewLine;
#if !KeePassLibSD #if !KeePassLibSD
if(excp.Source != null) if(excp.Source != null)
strText += excp.Source + MessageService.NewLine; strText += excp.Source + Environment.NewLine;
#endif #endif
if(excp.StackTrace != null) if(excp.StackTrace != null)
strText += excp.StackTrace + MessageService.NewLine; strText += excp.StackTrace + Environment.NewLine;
#if !KeePassLibSD #if !KeePassLibSD
#if !PCL && !KeePassRT
if(excp.TargetSite != null) if(excp.TargetSite != null)
strText += excp.TargetSite.ToString() + MessageService.NewLine; strText += excp.TargetSite.ToString() + MessageService.NewLine;
#endif
if(excp.Data != null) if(excp.Data != null)
{ {
strText += MessageService.NewLine; strText += Environment.NewLine;
foreach(DictionaryEntry de in excp.Data) foreach(DictionaryEntry de in excp.Data)
strText += @"'" + de.Key + @"' -> '" + de.Value + @"'" + strText += @"'" + de.Key + @"' -> '" + de.Value + @"'" +
MessageService.NewLine; Environment.NewLine;
} }
#endif #endif
if(excp.InnerException != null) if(excp.InnerException != null)
{ {
strText += MessageService.NewLine + "Inner:" + MessageService.NewLine; strText += Environment.NewLine + "Inner:" + Environment.NewLine;
if(excp.InnerException.Message != null) if(excp.InnerException.Message != null)
strText += excp.InnerException.Message + MessageService.NewLine; strText += excp.InnerException.Message + Environment.NewLine;
#if !KeePassLibSD #if !KeePassLibSD
if(excp.InnerException.Source != null) if(excp.InnerException.Source != null)
strText += excp.InnerException.Source + MessageService.NewLine; strText += excp.InnerException.Source + Environment.NewLine;
#endif #endif
if(excp.InnerException.StackTrace != null) if(excp.InnerException.StackTrace != null)
strText += excp.InnerException.StackTrace + MessageService.NewLine; strText += excp.InnerException.StackTrace + Environment.NewLine;
#if !KeePassLibSD #if !KeePassLibSD
#if !PCL && !KeePassRT
if(excp.InnerException.TargetSite != null) if(excp.InnerException.TargetSite != null)
strText += excp.InnerException.TargetSite.ToString(); strText += excp.InnerException.TargetSite.ToString();
#endif
if(excp.InnerException.Data != null) if(excp.InnerException.Data != null)
{ {
strText += MessageService.NewLine; strText += Environment.NewLine;
foreach(DictionaryEntry de in excp.InnerException.Data) foreach(DictionaryEntry de in excp.InnerException.Data)
strText += @"'" + de.Key + @"' -> '" + de.Value + @"'" + strText += @"'" + de.Key + @"' -> '" + de.Value + @"'" +
MessageService.NewLine; Environment.NewLine;
} }
#endif #endif
} }
return strText; return strText;
#endif
} }
public static bool TryParseUShort(string str, out ushort u) public static bool TryParseUShort(string str, out ushort u)
@@ -550,7 +561,25 @@ namespace ModernKeePassLib.Utility
return int.TryParse(str, out n); return int.TryParse(str, out n);
#else #else
try { n = int.Parse(str); return true; } try { n = int.Parse(str); return true; }
catch(Exception) { n = 0; return false; } catch(Exception) { n = 0; }
return false;
#endif
}
public static bool TryParseIntInvariant(string str, out int n)
{
#if !KeePassLibSD
return int.TryParse(str, NumberStyles.Integer,
NumberFormatInfo.InvariantInfo, out n);
#else
try
{
n = int.Parse(str, NumberStyles.Integer,
NumberFormatInfo.InvariantInfo);
return true;
}
catch(Exception) { n = 0; }
return false;
#endif #endif
} }
@@ -560,7 +589,25 @@ namespace ModernKeePassLib.Utility
return uint.TryParse(str, out u); return uint.TryParse(str, out u);
#else #else
try { u = uint.Parse(str); return true; } try { u = uint.Parse(str); return true; }
catch(Exception) { u = 0; return false; } catch(Exception) { u = 0; }
return false;
#endif
}
public static bool TryParseUIntInvariant(string str, out uint u)
{
#if !KeePassLibSD
return uint.TryParse(str, NumberStyles.Integer,
NumberFormatInfo.InvariantInfo, out u);
#else
try
{
u = uint.Parse(str, NumberStyles.Integer,
NumberFormatInfo.InvariantInfo);
return true;
}
catch(Exception) { u = 0; }
return false;
#endif #endif
} }
@@ -570,7 +617,25 @@ namespace ModernKeePassLib.Utility
return long.TryParse(str, out n); return long.TryParse(str, out n);
#else #else
try { n = long.Parse(str); return true; } try { n = long.Parse(str); return true; }
catch(Exception) { n = 0; return false; } catch(Exception) { n = 0; }
return false;
#endif
}
public static bool TryParseLongInvariant(string str, out long n)
{
#if !KeePassLibSD
return long.TryParse(str, NumberStyles.Integer,
NumberFormatInfo.InvariantInfo, out n);
#else
try
{
n = long.Parse(str, NumberStyles.Integer,
NumberFormatInfo.InvariantInfo);
return true;
}
catch(Exception) { n = 0; }
return false;
#endif #endif
} }
@@ -580,7 +645,25 @@ namespace ModernKeePassLib.Utility
return ulong.TryParse(str, out u); return ulong.TryParse(str, out u);
#else #else
try { u = ulong.Parse(str); return true; } try { u = ulong.Parse(str); return true; }
catch(Exception) { u = 0; return false; } catch(Exception) { u = 0; }
return false;
#endif
}
public static bool TryParseULongInvariant(string str, out ulong u)
{
#if !KeePassLibSD
return ulong.TryParse(str, NumberStyles.Integer,
NumberFormatInfo.InvariantInfo, out u);
#else
try
{
u = ulong.Parse(str, NumberStyles.Integer,
NumberFormatInfo.InvariantInfo);
return true;
}
catch(Exception) { u = 0; }
return false;
#endif #endif
} }
@@ -648,19 +731,34 @@ namespace ModernKeePassLib.Utility
Debug.Assert(strText != null); // No throw Debug.Assert(strText != null); // No throw
if(string.IsNullOrEmpty(strText)) return strText; if(string.IsNullOrEmpty(strText)) return strText;
char[] vChars = strText.ToCharArray(); int nLength = strText.Length;
StringBuilder sb = new StringBuilder(strText.Length, strText.Length); StringBuilder sb = new StringBuilder(nLength);
char ch;
for(int i = 0; i < vChars.Length; ++i) for(int i = 0; i < nLength; ++i)
{ {
ch = vChars[i]; char ch = strText[i];
if(((ch >= 0x20) && (ch <= 0xD7FF)) || if(((ch >= '\u0020') && (ch <= '\uD7FF')) ||
(ch == 0x9) || (ch == 0xA) || (ch == 0xD) || (ch == '\u0009') || (ch == '\u000A') || (ch == '\u000D') ||
((ch >= 0xE000) && (ch <= 0xFFFD))) ((ch >= '\uE000') && (ch <= '\uFFFD')))
sb.Append(ch); sb.Append(ch);
// Range ((ch >= 0x10000) && (ch <= 0x10FFFF)) excluded else if((ch >= '\uD800') && (ch <= '\uDBFF')) // High surrogate
{
if((i + 1) < nLength)
{
char chLow = strText[i + 1];
if((chLow >= '\uDC00') && (chLow <= '\uDFFF')) // Low sur.
{
sb.Append(ch);
sb.Append(chLow);
++i;
}
else { Debug.Assert(false); } // Low sur. invalid
}
else { Debug.Assert(false); } // Low sur. missing
}
Debug.Assert((ch < '\uDC00') || (ch > '\uDFFF')); // Lonely low sur.
} }
return sb.ToString(); return sb.ToString();
@@ -669,22 +767,24 @@ namespace ModernKeePassLib.Utility
private static Regex m_rxNaturalSplit = null; private static Regex m_rxNaturalSplit = null;
public static int CompareNaturally(string strX, string strY) public static int CompareNaturally(string strX, string strY)
{ {
Debug.Assert(false, "not yet implemented");
return 0;
#if TODO
Debug.Assert(strX != null); Debug.Assert(strX != null);
if(strX == null) throw new ArgumentNullException("strX"); if(strX == null) throw new ArgumentNullException("strX");
Debug.Assert(strY != null); Debug.Assert(strY != null);
if(strY == null) throw new ArgumentNullException("strY"); if(strY == null) throw new ArgumentNullException("strY");
if(NativeMethods.SupportsStrCmpNaturally) /*if(NativeMethods.SupportsStrCmpNaturally)
return NativeMethods.StrCmpNaturally(strX, strY); return NativeMethods.StrCmpNaturally(strX, strY);*/
strX = strX.ToLower(); // Case-insensitive comparison strX = strX.ToLower(); // Case-insensitive comparison
strY = strY.ToLower(); strY = strY.ToLower();
if(m_rxNaturalSplit == null) if(m_rxNaturalSplit == null)
m_rxNaturalSplit = new Regex(@"([0-9]+)", RegexOptions.Compiled); m_rxNaturalSplit = new Regex(@"([0-9]+)",
#if PCL || KeePassRT
RegexOptions.None);
#else
RegexOptions.Compiled);
#endif
string[] vPartsX = m_rxNaturalSplit.Split(strX); string[] vPartsX = m_rxNaturalSplit.Split(strX);
string[] vPartsY = m_rxNaturalSplit.Split(strY); string[] vPartsY = m_rxNaturalSplit.Split(strY);
@@ -716,7 +816,6 @@ namespace ModernKeePassLib.Utility
if(vPartsX.Length == vPartsY.Length) return 0; if(vPartsX.Length == vPartsY.Length) return 0;
if(vPartsX.Length < vPartsY.Length) return -1; if(vPartsX.Length < vPartsY.Length) return -1;
return 1; return 1;
#endif
} }
public static string RemoveAccelerator(string strMenuText) public static string RemoveAccelerator(string strMenuText)
@@ -740,6 +839,54 @@ namespace ModernKeePassLib.Utility
return str; return str;
} }
public static string AddAccelerator(string strMenuText,
List<char> lAvailKeys)
{
if(strMenuText == null) { Debug.Assert(false); return null; }
if(lAvailKeys == null) { Debug.Assert(false); return strMenuText; }
int xa = -1, xs = 0;
for(int i = 0; i < strMenuText.Length; ++i)
{
char ch = strMenuText[i];
#if KeePassLibSD
char chUpper = char.ToUpper(ch);
#else
char chUpper = char.ToUpperInvariant(ch);
#endif
xa = lAvailKeys.IndexOf(chUpper);
if(xa >= 0) { xs = i; break; }
#if KeePassLibSD
char chLower = char.ToLower(ch);
#else
char chLower = char.ToLowerInvariant(ch);
#endif
xa = lAvailKeys.IndexOf(chLower);
if(xa >= 0) { xs = i; break; }
}
if(xa < 0) return strMenuText;
lAvailKeys.RemoveAt(xa);
return strMenuText.Insert(xs, @"&");
}
public static string EncodeMenuText(string strText)
{
if(strText == null) throw new ArgumentNullException("strText");
return strText.Replace(@"&", @"&&");
}
public static string EncodeToolTipText(string strText)
{
if(strText == null) throw new ArgumentNullException("strText");
return strText.Replace(@"&", @"&&&");
}
public static bool IsHexString(string str, bool bStrict) public static bool IsHexString(string str, bool bStrict)
{ {
if(str == null) throw new ArgumentNullException("str"); if(str == null) throw new ArgumentNullException("str");
@@ -888,6 +1035,36 @@ namespace ModernKeePassLib.Utility
} }
} }
public static string GetNewLineSeq(string str)
{
if(str == null) { Debug.Assert(false); return Environment.NewLine; }
int n = str.Length, nLf = 0, nCr = 0, nCrLf = 0;
char chLast = char.MinValue;
for(int i = 0; i < n; ++i)
{
char ch = str[i];
if(ch == '\r') ++nCr;
else if(ch == '\n')
{
++nLf;
if(chLast == '\r') ++nCrLf;
}
chLast = ch;
}
nCr -= nCrLf;
nLf -= nCrLf;
int nMax = Math.Max(nCrLf, Math.Max(nCr, nLf));
if(nMax == 0) return Environment.NewLine;
if(nCrLf == nMax) return "\r\n";
return ((nLf == nMax) ? "\n" : "\r");
}
public static string AlphaNumericOnly(string str) public static string AlphaNumericOnly(string str)
{ {
if(string.IsNullOrEmpty(str)) return str; if(string.IsNullOrEmpty(str)) return str;
@@ -965,85 +1142,85 @@ namespace ModernKeePassLib.Utility
public static string VersionToString(ulong uVersion) public static string VersionToString(ulong uVersion)
{ {
return VersionToString(uVersion, false); return VersionToString(uVersion, 1U);
} }
[Obsolete]
public static string VersionToString(ulong uVersion, public static string VersionToString(ulong uVersion,
bool bEnsureAtLeastTwoComp) bool bEnsureAtLeastTwoComp)
{ {
string str = string.Empty; return VersionToString(uVersion, (bEnsureAtLeastTwoComp ? 2U : 1U));
bool bMultiComp = false; }
public static string VersionToString(ulong uVersion, uint uMinComp)
{
StringBuilder sb = new StringBuilder();
uint uComp = 0;
for(int i = 0; i < 4; ++i) for(int i = 0; i < 4; ++i)
{ {
ushort us = (ushort)(uVersion & 0xFFFFUL); if(uVersion == 0UL) break;
if((us != 0) || (str.Length > 0)) ushort us = (ushort)(uVersion >> 48);
{
if(str.Length > 0)
{
str = "." + str;
bMultiComp = true;
}
str = us.ToString() + str; if(sb.Length > 0) sb.Append('.');
}
uVersion >>= 16; sb.Append(us.ToString(NumberFormatInfo.InvariantInfo));
++uComp;
uVersion <<= 16;
} }
if(bEnsureAtLeastTwoComp && !bMultiComp && (str.Length > 0)) while(uComp < uMinComp)
str += ".0"; {
if(sb.Length > 0) sb.Append('.');
return str; sb.Append('0');
++uComp;
}
return sb.ToString();
} }
private static readonly byte[] m_pbOptEnt = { 0xA5, 0x74, 0x2E, 0xEC }; private static readonly byte[] m_pbOptEnt = { 0xA5, 0x74, 0x2E, 0xEC };
public static string EncryptString(string strPlainText) public static string EncryptString(string strPlainText)
{ {
Debug.Assert(false, "not yet implemented");
return null;
#if TODO
if(string.IsNullOrEmpty(strPlainText)) return string.Empty; if(string.IsNullOrEmpty(strPlainText)) return string.Empty;
try try
{ {
byte[] pbPlain = StrUtil.Utf8.GetBytes(strPlainText); byte[] pbPlain = StrUtil.Utf8.GetBytes(strPlainText);
byte[] pbEnc = ProtectedData.Protect(pbPlain, m_pbOptEnt,
DataProtectionScope.CurrentUser);
#if !KeePassLibSD var provider = new DataProtectionProvider("Local=user");
var pbEnc = provider.ProtectAsync(pbPlain.AsBuffer()).GetResults();
#if (!PCL && !KeePassLibSD && !KeePassRT)
return Convert.ToBase64String(pbEnc, Base64FormattingOptions.None); return Convert.ToBase64String(pbEnc, Base64FormattingOptions.None);
#else #else
return Convert.ToBase64String(pbEnc); return Convert.ToBase64String(pbEnc.ToArray());
#endif #endif
} }
catch(Exception) { Debug.Assert(false); } catch(Exception) { Debug.Assert(false); }
return strPlainText; return strPlainText;
#endif
} }
public static string DecryptString(string strCipherText) public static string DecryptString(string strCipherText)
{ {
Debug.Assert(false, "not yet implemented");
return null;
#if TODO
if(string.IsNullOrEmpty(strCipherText)) return string.Empty; if(string.IsNullOrEmpty(strCipherText)) return string.Empty;
try try
{ {
byte[] pbEnc = Convert.FromBase64String(strCipherText); byte[] pbEnc = Convert.FromBase64String(strCipherText);
byte[] pbPlain = ProtectedData.Unprotect(pbEnc, m_pbOptEnt, var provider = new DataProtectionProvider("Local=user");
DataProtectionScope.CurrentUser); var pbPlain = provider.UnprotectAsync(pbEnc.AsBuffer()).GetResults().ToArray();
return StrUtil.Utf8.GetString(pbPlain, 0, pbPlain.Length); return StrUtil.Utf8.GetString(pbPlain, 0, pbPlain.Length);
} }
catch(Exception) { Debug.Assert(false); } catch(Exception) { Debug.Assert(false); }
return strCipherText; return strCipherText;
#endif
} }
public static string SerializeIntArray(int[] vNumbers) public static string SerializeIntArray(int[] vNumbers)
@@ -1054,7 +1231,7 @@ namespace ModernKeePassLib.Utility
for(int i = 0; i < vNumbers.Length; ++i) for(int i = 0; i < vNumbers.Length; ++i)
{ {
if(i > 0) sb.Append(' '); if(i > 0) sb.Append(' ');
sb.Append(vNumbers[i]); sb.Append(vNumbers[i].ToString(NumberFormatInfo.InvariantInfo));
} }
return sb.ToString(); return sb.ToString();
@@ -1071,7 +1248,7 @@ namespace ModernKeePassLib.Utility
for(int i = 0; i < vParts.Length; ++i) for(int i = 0; i < vParts.Length; ++i)
{ {
int n; int n;
if(!TryParseInt(vParts[i], out n)) { Debug.Assert(false); } if(!TryParseIntInvariant(vParts[i], out n)) { Debug.Assert(false); }
v[i] = n; v[i] = n;
} }
@@ -1131,7 +1308,7 @@ namespace ModernKeePassLib.Utility
Array.Reverse(pb); Array.Reverse(pb);
for(int i = 0; i < pb.Length; ++i) pb[i] = (byte)(pb[i] ^ 0x65); for(int i = 0; i < pb.Length; ++i) pb[i] = (byte)(pb[i] ^ 0x65);
#if !KeePassLibSD && TODO #if (!PCL && !KeePassLibSD && !KeePassRT)
return Convert.ToBase64String(pb, Base64FormattingOptions.None); return Convert.ToBase64String(pb, Base64FormattingOptions.None);
#else #else
return Convert.ToBase64String(pb); return Convert.ToBase64String(pb);
@@ -1249,9 +1426,33 @@ namespace ModernKeePassLib.Utility
public static bool IsDataUri(string strUri) public static bool IsDataUri(string strUri)
{ {
if(strUri == null) { Debug.Assert(false); return false; } return IsDataUri(strUri, null);
}
return strUri.StartsWith("data:", StrUtil.CaseIgnoreCmp); public static bool IsDataUri(string strUri, string strReqMimeType)
{
if(strUri == null) { Debug.Assert(false); return false; }
// strReqMimeType may be null
const string strPrefix = "data:";
if(!strUri.StartsWith(strPrefix, StrUtil.CaseIgnoreCmp))
return false;
int iC = strUri.IndexOf(',');
if(iC < 0) return false;
if(!string.IsNullOrEmpty(strReqMimeType))
{
int iS = strUri.IndexOf(';', 0, iC);
int iTerm = ((iS >= 0) ? iS : iC);
string strMime = strUri.Substring(strPrefix.Length,
iTerm - strPrefix.Length);
if(!strMime.Equals(strReqMimeType, StrUtil.CaseIgnoreCmp))
return false;
}
return true;
} }
/// <summary> /// <summary>
@@ -1267,7 +1468,7 @@ namespace ModernKeePassLib.Utility
if(strMimeType == null) strMimeType = "application/octet-stream"; if(strMimeType == null) strMimeType = "application/octet-stream";
#if !KeePassLibSD && TODO #if (!PCL && !KeePassLibSD && !KeePassRT)
return ("data:" + strMimeType + ";base64," + Convert.ToBase64String( return ("data:" + strMimeType + ";base64," + Convert.ToBase64String(
pbData, Base64FormattingOptions.None)); pbData, Base64FormattingOptions.None));
#else #else
@@ -1283,9 +1484,6 @@ namespace ModernKeePassLib.Utility
/// <returns>Decoded binary data.</returns> /// <returns>Decoded binary data.</returns>
public static byte[] DataUriToData(string strDataUri) public static byte[] DataUriToData(string strDataUri)
{ {
Debug.Assert(false, "not yet implemented");
return null;
#if TODO
if(strDataUri == null) throw new ArgumentNullException("strDataUri"); if(strDataUri == null) throw new ArgumentNullException("strDataUri");
if(!strDataUri.StartsWith("data:", StrUtil.CaseIgnoreCmp)) return null; if(!strDataUri.StartsWith("data:", StrUtil.CaseIgnoreCmp)) return null;
@@ -1301,20 +1499,25 @@ namespace ModernKeePassLib.Utility
MemoryStream ms = new MemoryStream(); MemoryStream ms = new MemoryStream();
#if PCL || KeePassRT
Encoding enc = StrUtil.Utf8;
#else
Encoding enc = Encoding.ASCII;
#endif
string[] v = strData.Split('%'); string[] v = strData.Split('%');
byte[] pb = Encoding.ASCII.GetBytes(v[0]); byte[] pb = enc.GetBytes(v[0]);
ms.Write(pb, 0, pb.Length); ms.Write(pb, 0, pb.Length);
for(int i = 1; i < v.Length; ++i) for(int i = 1; i < v.Length; ++i)
{ {
ms.WriteByte(Convert.ToByte(v[i].Substring(0, 2), 16)); ms.WriteByte(Convert.ToByte(v[i].Substring(0, 2), 16));
pb = Encoding.ASCII.GetBytes(v[i].Substring(2)); pb = enc.GetBytes(v[i].Substring(2));
ms.Write(pb, 0, pb.Length); ms.Write(pb, 0, pb.Length);
} }
pb = ms.ToArray(); pb = ms.ToArray();
ms.Close(); ms.Dispose();
return pb; return pb;
#endif
} }
/// <summary> /// <summary>
@@ -1358,5 +1561,72 @@ namespace ModernKeePassLib.Utility
return null; return null;
} }
private static string[] m_vPrefSepChars = null;
/// <summary>
/// Find a character that does not occur within a given text.
/// </summary>
public static char GetUnusedChar(string strText)
{
if(strText == null) { Debug.Assert(false); return '@'; }
if(m_vPrefSepChars == null)
m_vPrefSepChars = new string[5] {
"@!$%#/\\:;,.*-_?",
PwCharSet.UpperCase, PwCharSet.LowerCase,
PwCharSet.Digits, PwCharSet.PrintableAsciiSpecial
};
for(int i = 0; i < m_vPrefSepChars.Length; ++i)
{
foreach(char ch in m_vPrefSepChars[i])
{
if(strText.IndexOf(ch) < 0) return ch;
}
}
for(char ch = '\u00C0'; ch < char.MaxValue; ++ch)
{
if(strText.IndexOf(ch) < 0) return ch;
}
return char.MinValue;
}
public static char ByteToSafeChar(byte bt)
{
const char chDefault = '.';
// 00-1F are C0 control chars
if(bt < 0x20) return chDefault;
// 20-7F are basic Latin; 7F is DEL
if(bt < 0x7F) return (char)bt;
// 80-9F are C1 control chars
if(bt < 0xA0) return chDefault;
// A0-FF are Latin-1 supplement; AD is soft hyphen
if(bt == 0xAD) return '-';
return (char)bt;
}
public static int Count(string str, string strNeedle)
{
if(str == null) { Debug.Assert(false); return 0; }
if(string.IsNullOrEmpty(strNeedle)) { Debug.Assert(false); return 0; }
int iOffset = 0, iCount = 0;
while(iOffset < str.Length)
{
int p = str.IndexOf(strNeedle, iOffset);
if(p < 0) break;
++iCount;
iOffset = p + 1;
}
return iCount;
}
} }
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -18,8 +18,13 @@
*/ */
using System; using System;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
using System.Diagnostics; using System.Diagnostics;
using ModernKeePassLib.Interfaces;
namespace ModernKeePassLib.Utility namespace ModernKeePassLib.Utility
{ {
/// <summary> /// <summary>
@@ -33,6 +38,11 @@ namespace ModernKeePassLib.Utility
/// </summary> /// </summary>
public const int PwTimeLength = 7; public const int PwTimeLength = 7;
#if !KeePassLibSD
private static string m_strDtfStd = null;
private static string m_strDtfDate = null;
#endif
/// <summary> /// <summary>
/// Pack a <c>DateTime</c> object into 5 bytes. Layout: 2 zero bits, /// Pack a <c>DateTime</c> object into 5 bytes. Layout: 2 zero bits,
/// year 12 bits, month 4 bits, day 5 bits, hour 5 bits, minute 6 /// year 12 bits, month 4 bits, day 5 bits, hour 5 bits, minute 6
@@ -138,17 +148,118 @@ namespace ModernKeePassLib.Utility
{ {
DateTime dt; DateTime dt;
#if !KeePassLibSD #if KeePassLibSD
if(DateTime.TryParse(strDisplay, out dt)) return dt;
#else
try { dt = DateTime.Parse(strDisplay); return dt; } try { dt = DateTime.Parse(strDisplay); return dt; }
catch(Exception) { } catch(Exception) { }
#else
if(DateTime.TryParse(strDisplay, out dt)) return dt;
// For some custom formats specified using the Control Panel,
// DateTime.ToString returns the correct string, but
// DateTime.TryParse fails (e.g. for "//dd/MMM/yyyy");
// https://sourceforge.net/p/keepass/discussion/329221/thread/3a225b29/?limit=25&page=1#c6ae
if((m_strDtfStd == null) || (m_strDtfDate == null))
{
DateTime dtUni = new DateTime(2111, 3, 4, 5, 6, 7);
m_strDtfStd = DeriveCustomFormat(ToDisplayString(dtUni), dtUni);
m_strDtfDate = DeriveCustomFormat(ToDisplayStringDateOnly(dtUni), dtUni);
}
const DateTimeStyles dts = DateTimeStyles.AllowWhiteSpaces;
if(DateTime.TryParseExact(strDisplay, m_strDtfStd, null, dts, out dt))
return dt;
if(DateTime.TryParseExact(strDisplay, m_strDtfDate, null, dts, out dt))
return dt;
#endif #endif
Debug.Assert(false); Debug.Assert(false);
return DateTime.Now; return DateTime.Now;
} }
#if !KeePassLibSD
private static string DeriveCustomFormat(string strDT, DateTime dt)
{
string[] vPlh = new string[] {
// Names, sorted by length
"MMMM", "dddd",
"MMM", "ddd",
"gg", "g",
// Numbers, the ones with prefix '0' first
"yyyy", "yyy", "yy", "y",
"MM", "M",
"dd", "d",
"HH", "hh", "H", "h",
"mm", "m",
"ss", "s",
"tt", "t"
};
List<string> lValues = new List<string>();
foreach(string strPlh in vPlh)
{
string strEval = strPlh;
if(strEval.Length == 1) strEval = @"%" + strPlh; // Make custom
lValues.Add(dt.ToString(strEval));
}
StringBuilder sbAll = new StringBuilder();
sbAll.Append("dfFghHKmMstyz:/\"\'\\%");
sbAll.Append(strDT);
foreach(string strVEnum in lValues) { sbAll.Append(strVEnum); }
List<char> lCodes = new List<char>();
for(int i = 0; i < vPlh.Length; ++i)
{
char ch = StrUtil.GetUnusedChar(sbAll.ToString());
lCodes.Add(ch);
sbAll.Append(ch);
}
string str = strDT;
for(int i = 0; i < vPlh.Length; ++i)
{
string strValue = lValues[i];
if(string.IsNullOrEmpty(strValue)) continue;
str = str.Replace(strValue, new string(lCodes[i], 1));
}
StringBuilder sbFmt = new StringBuilder();
bool bInLiteral = false;
foreach(char ch in str)
{
int iCode = lCodes.IndexOf(ch);
// The escape character doesn't work correctly (e.g.
// "dd\\.MM\\.yyyy\\ HH\\:mm\\:ss" doesn't work, but
// "dd'.'MM'.'yyyy' 'HH':'mm':'ss" does); use '' instead
// if(iCode >= 0) sbFmt.Append(vPlh[iCode]);
// else // Literal
// {
// sbFmt.Append('\\');
// sbFmt.Append(ch);
// }
if(iCode >= 0)
{
if(bInLiteral) { sbFmt.Append('\''); bInLiteral = false; }
sbFmt.Append(vPlh[iCode]);
}
else // Literal
{
if(!bInLiteral) { sbFmt.Append('\''); bInLiteral = true; }
sbFmt.Append(ch);
}
}
if(bInLiteral) sbFmt.Append('\'');
return sbFmt.ToString();
}
#endif
public static string SerializeUtc(DateTime dt) public static string SerializeUtc(DateTime dt)
{ {
string str = dt.ToUniversalTime().ToString("s"); string str = dt.ToUniversalTime().ToString("s");
@@ -218,5 +329,44 @@ namespace ModernKeePassLib.Utility
return null; return null;
} }
#endif #endif
private static readonly DateTime m_dtInvMin =
new DateTime(2999, 12, 27, 23, 59, 59);
private static readonly DateTime m_dtInvMax =
new DateTime(2999, 12, 29, 23, 59, 59);
public static int Compare(DateTime dtA, DateTime dtB, bool bUnkIsPast)
{
if(bUnkIsPast)
{
// 2999-12-28 23:59:59 in KeePass 1.x means 'unknown';
// expect time zone corruption (twice)
// bool bInvA = ((dtA.Year == 2999) && (dtA.Month == 12) &&
// (dtA.Day >= 27) && (dtA.Day <= 29) && (dtA.Minute == 59) &&
// (dtA.Second == 59));
// bool bInvB = ((dtB.Year == 2999) && (dtB.Month == 12) &&
// (dtB.Day >= 27) && (dtB.Day <= 29) && (dtB.Minute == 59) &&
// (dtB.Second == 59));
// Faster due to internal implementation of DateTime:
bool bInvA = ((dtA >= m_dtInvMin) && (dtA <= m_dtInvMax) &&
(dtA.Minute == 59) && (dtA.Second == 59));
bool bInvB = ((dtB >= m_dtInvMin) && (dtB <= m_dtInvMax) &&
(dtB.Minute == 59) && (dtB.Second == 59));
if(bInvA) return (bInvB ? 0 : -1);
if(bInvB) return 1;
}
return dtA.CompareTo(dtB);
}
internal static int CompareLastMod(ITimeLogger tlA, ITimeLogger tlB,
bool bUnkIsPast)
{
if(tlA == null) { Debug.Assert(false); return ((tlB == null) ? 0 : -1); }
if(tlB == null) { Debug.Assert(false); return 1; }
return Compare(tlA.LastModificationTime, tlB.LastModificationTime,
bUnkIsPast);
}
} }
} }

View File

@@ -1,6 +1,6 @@
/* /*
KeePass Password Safe - The Open-Source Password Manager KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de> Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -20,11 +20,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Diagnostics;
using ModernKeePassLib.Native; #if PCL
using Windows.Storage;
#endif
namespace ModernKeePassLib.Utility namespace ModernKeePassLib.Utility
{ {
@@ -34,16 +36,30 @@ namespace ModernKeePassLib.Utility
/// </summary> /// </summary>
public static class UrlUtil public static class UrlUtil
{ {
// Bert TODO: Temporary fix, most of this class is not needed in WINRT. private static readonly char[] m_vDirSeps = new char[] {
private static readonly char DirectorySeparatorChar = '/'; '\\', '/', UrlUtil.LocalDirSepChar };
#if !PCL
private static readonly char[] m_vPathTrimCharsWs = new char[] {
'\"', ' ', '\t', '\r', '\n' };
#endif
private static readonly char[] m_vDirSeps = new char[] { '\\', '/', public static char LocalDirSepChar
DirectorySeparatorChar }; {
#if KeePassRT
get { return '\\'; }
#elif PCL
//get { return PortablePath.DirectorySeparatorChar; }
get { return '\\'; }
#else
get { return Path.DirectorySeparatorChar; }
#endif
}
/// <summary> /// <summary>
/// Get the directory (path) of a file name. The returned string is /// Get the directory (path) of a file name. The returned string may be
/// terminated by a directory separator character. Example: /// terminated by a directory separator character. Example:
/// passing <c>C:\\My Documents\\My File.kdb</c> in <paramref name="strFile" /> /// passing <c>C:\\My Documents\\My File.kdb</c> in <paramref name="strFile" />
/// and <c>true</c> to <paramref name="bAppendTerminatingChar"/>
/// would produce this string: <c>C:\\My Documents\\</c>. /// would produce this string: <c>C:\\My Documents\\</c>.
/// </summary> /// </summary>
/// <param name="strFile">Full path of a file.</param> /// <param name="strFile">Full path of a file.</param>
@@ -54,8 +70,7 @@ namespace ModernKeePassLib.Utility
/// of <c>X:</c>, overriding <paramref name="bAppendTerminatingChar" />). /// of <c>X:</c>, overriding <paramref name="bAppendTerminatingChar" />).
/// This should only be set to <c>true</c>, if the returned path is directly /// This should only be set to <c>true</c>, if the returned path is directly
/// passed to some directory API.</param> /// passed to some directory API.</param>
/// <returns>Directory of the file. The return value is an empty string /// <returns>Directory of the file.</returns>
/// (<c>""</c>) if the input parameter is <c>null</c>.</returns>
public static string GetFileDirectory(string strFile, bool bAppendTerminatingChar, public static string GetFileDirectory(string strFile, bool bAppendTerminatingChar,
bool bEnsureValidDirSpec) bool bEnsureValidDirSpec)
{ {
@@ -63,14 +78,15 @@ namespace ModernKeePassLib.Utility
if(strFile == null) throw new ArgumentNullException("strFile"); if(strFile == null) throw new ArgumentNullException("strFile");
int nLastSep = strFile.LastIndexOfAny(m_vDirSeps); int nLastSep = strFile.LastIndexOfAny(m_vDirSeps);
if(nLastSep < 0) return strFile; // None if(nLastSep < 0) return string.Empty; // No directory
if(bEnsureValidDirSpec && (nLastSep == 2) && (strFile[1] == ':') && if(bEnsureValidDirSpec && (nLastSep == 2) && (strFile[1] == ':') &&
(strFile[2] == '\\')) // Length >= 3 and Windows root directory (strFile[2] == '\\')) // Length >= 3 and Windows root directory
bAppendTerminatingChar = true; bAppendTerminatingChar = true;
if(!bAppendTerminatingChar) return strFile.Substring(0, nLastSep); if(!bAppendTerminatingChar) return strFile.Substring(0, nLastSep);
return EnsureTerminatingSeparator(strFile.Substring(0, nLastSep), false); return EnsureTerminatingSeparator(strFile.Substring(0, nLastSep),
(strFile[nLastSep] == '/'));
} }
/// <summary> /// <summary>
@@ -151,7 +167,7 @@ namespace ModernKeePassLib.Utility
} }
if(bUrl) return (strPath + '/'); if(bUrl) return (strPath + '/');
return (strPath + DirectorySeparatorChar); return (strPath + UrlUtil.LocalDirSepChar);
} }
/* /// <summary> /* /// <summary>
@@ -214,13 +230,22 @@ namespace ModernKeePassLib.Utility
public static string GetQuotedAppPath(string strPath) public static string GetQuotedAppPath(string strPath)
{ {
int nFirst = strPath.IndexOf('\"'); if(strPath == null) { Debug.Assert(false); return string.Empty; }
int nSecond = strPath.IndexOf('\"', nFirst + 1);
if((nFirst >= 0) && (nSecond >= 0)) // int nFirst = strPath.IndexOf('\"');
return strPath.Substring(nFirst + 1, nSecond - nFirst - 1); // int nSecond = strPath.IndexOf('\"', nFirst + 1);
// if((nFirst >= 0) && (nSecond >= 0))
// return strPath.Substring(nFirst + 1, nSecond - nFirst - 1);
// return strPath;
return strPath; string str = strPath.Trim();
if(str.Length <= 1) return str;
if(str[0] != '\"') return str;
int iSecond = str.IndexOf('\"', 1);
if(iSecond <= 0) return str;
return str.Substring(1, iSecond - 1);
} }
public static string FileUrlToPath(string strUrl) public static string FileUrlToPath(string strUrl)
@@ -232,14 +257,14 @@ namespace ModernKeePassLib.Utility
if(str.StartsWith(@"file:///", StrUtil.CaseIgnoreCmp)) if(str.StartsWith(@"file:///", StrUtil.CaseIgnoreCmp))
str = str.Substring(8, str.Length - 8); str = str.Substring(8, str.Length - 8);
str = str.Replace('/', DirectorySeparatorChar); str = str.Replace('/', UrlUtil.LocalDirSepChar);
return str; return str;
} }
public static bool UnhideFile(string strFile) public static bool UnhideFile(string strFile)
{ {
#if KeePassLibSD || !TODO #if (PCL || KeePassLibSD || KeePassRT)
return false; return false;
#else #else
if(strFile == null) throw new ArgumentNullException("strFile"); if(strFile == null) throw new ArgumentNullException("strFile");
@@ -259,7 +284,7 @@ namespace ModernKeePassLib.Utility
public static bool HideFile(string strFile, bool bHide) public static bool HideFile(string strFile, bool bHide)
{ {
#if KeePassLibSD || !TODO #if (PCL || KeePassLibSD || KeePassRT)
return false; return false;
#else #else
if(strFile == null) throw new ArgumentNullException("strFile"); if(strFile == null) throw new ArgumentNullException("strFile");
@@ -300,7 +325,9 @@ namespace ModernKeePassLib.Utility
return strTargetFile; return strTargetFile;
} }
#if (!PCL && !KeePassLibSD && !KeePassRT)
if(NativeLib.IsUnix()) if(NativeLib.IsUnix())
#endif
{ {
bool bBaseUnc = IsUncPath(strBaseFile); bool bBaseUnc = IsUncPath(strBaseFile);
bool bTargetUnc = IsUncPath(strTargetFile); bool bTargetUnc = IsUncPath(strTargetFile);
@@ -319,21 +346,19 @@ namespace ModernKeePassLib.Utility
StringBuilder sbRel = new StringBuilder(); StringBuilder sbRel = new StringBuilder();
for(int j = i; j < (vBase.Length - 1); ++j) for(int j = i; j < (vBase.Length - 1); ++j)
{ {
if(sbRel.Length > 0) sbRel.Append(DirectorySeparatorChar); if(sbRel.Length > 0) sbRel.Append(UrlUtil.LocalDirSepChar);
sbRel.Append(".."); sbRel.Append("..");
} }
for(int k = i; k < vTarget.Length; ++k) for(int k = i; k < vTarget.Length; ++k)
{ {
if(sbRel.Length > 0) sbRel.Append(DirectorySeparatorChar); if(sbRel.Length > 0) sbRel.Append(UrlUtil.LocalDirSepChar);
sbRel.Append(vTarget[k]); sbRel.Append(vTarget[k]);
} }
return sbRel.ToString(); return sbRel.ToString();
} }
#if KeePassLibSD || !TODO #if (!PCL && !KeePassLibSD && !KeePassRT)
return strTargetFile;
#else
try // Windows try // Windows
{ {
const int nMaxPath = NativeMethods.MAX_PATH * 2; const int nMaxPath = NativeMethods.MAX_PATH * 2;
@@ -347,7 +372,8 @@ namespace ModernKeePassLib.Utility
return str; return str;
} }
catch(Exception) { Debug.Assert(false); return strTargetFile; } catch(Exception) { Debug.Assert(false); }
return strTargetFile;
#endif #endif
} }
@@ -379,9 +405,6 @@ namespace ModernKeePassLib.Utility
public static string GetShortestAbsolutePath(string strPath) public static string GetShortestAbsolutePath(string strPath)
{ {
Debug.Assert(false, "not yet implemented");
return null;
#if TODO
if(strPath == null) throw new ArgumentNullException("strPath"); if(strPath == null) throw new ArgumentNullException("strPath");
if(strPath.Length == 0) return string.Empty; if(strPath.Length == 0) return string.Empty;
@@ -426,7 +449,20 @@ namespace ModernKeePassLib.Utility
} }
string str; string str;
try { str = Path.GetFullPath(strPath); } try
{
#if KeePassRT
var dirT = StorageFolder.GetFolderFromPathAsync(
strPath).GetResults();
str = dirT.Path;
#elif PCL
//var dirT = FileSystem.Current.GetFolderFromPathAsync(strPath).Result;
str = ApplicationData.Current.RoamingFolder.Path;
//str = dirT.Path;
#else
str = Path.GetFullPath(strPath);
#endif
}
catch(Exception) { Debug.Assert(false); return strPath; } catch(Exception) { Debug.Assert(false); return strPath; }
Debug.Assert(str.IndexOf("\\..\\") < 0); Debug.Assert(str.IndexOf("\\..\\") < 0);
@@ -437,7 +473,6 @@ namespace ModernKeePassLib.Utility
} }
return str; return str;
#endif
} }
public static int GetUrlLength(string strText, int nOffset) public static int GetUrlLength(string strText, int nOffset)
@@ -483,7 +518,7 @@ namespace ModernKeePassLib.Utility
public static string ConvertSeparators(string strPath) public static string ConvertSeparators(string strPath)
{ {
return ConvertSeparators(strPath, DirectorySeparatorChar); return ConvertSeparators(strPath, UrlUtil.LocalDirSepChar);
} }
public static string ConvertSeparators(string strPath, char chSeparator) public static string ConvertSeparators(string strPath, char chSeparator)
@@ -595,5 +630,106 @@ namespace ModernKeePassLib.Utility
return false; return false;
} }
#if !PCL
public static string GetTempPath()
{
string strDir;
if(NativeLib.IsUnix())
strDir = NativeMethods.GetUserRuntimeDir();
#if KeePassRT
else strDir = Windows.Storage.ApplicationData.Current.TemporaryFolder.Path;
#else
else strDir = Path.GetTempPath();
#endif
try
{
if(Directory.Exists(strDir) == false)
Directory.CreateDirectory(strDir);
}
catch(Exception) { Debug.Assert(false); }
return strDir;
}
#endif
#if !PCL && !KeePassLibSD
// Structurally mostly equivalent to UrlUtil.GetFileInfos
public static List<string> GetFilePaths(string strDir, string strPattern,
SearchOption opt)
{
List<string> l = new List<string>();
if(strDir == null) { Debug.Assert(false); return l; }
if(strPattern == null) { Debug.Assert(false); return l; }
string[] v = Directory.GetFiles(strDir, strPattern, opt);
if(v == null) { Debug.Assert(false); return l; }
// Only accept files with the correct extension; GetFiles may
// return additional files, see GetFiles documentation
string strExt = GetExtension(strPattern);
if(!string.IsNullOrEmpty(strExt) && (strExt.IndexOf('*') < 0) &&
(strExt.IndexOf('?') < 0))
{
strExt = "." + strExt;
foreach(string strPathRaw in v)
{
if(strPathRaw == null) { Debug.Assert(false); continue; }
string strPath = strPathRaw.Trim(m_vPathTrimCharsWs);
if(strPath.Length == 0) { Debug.Assert(false); continue; }
Debug.Assert(strPath == strPathRaw);
if(!strPath.EndsWith(strExt, StrUtil.CaseIgnoreCmp))
continue;
l.Add(strPathRaw);
}
}
else l.AddRange(v);
return l;
}
// Structurally mostly equivalent to UrlUtil.GetFilePaths
public static List<FileInfo> GetFileInfos(DirectoryInfo di, string strPattern,
SearchOption opt)
{
List<FileInfo> l = new List<FileInfo>();
if(di == null) { Debug.Assert(false); return l; }
if(strPattern == null) { Debug.Assert(false); return l; }
FileInfo[] v = di.GetFiles(strPattern, opt);
if(v == null) { Debug.Assert(false); return l; }
// Only accept files with the correct extension; GetFiles may
// return additional files, see GetFiles documentation
string strExt = GetExtension(strPattern);
if(!string.IsNullOrEmpty(strExt) && (strExt.IndexOf('*') < 0) &&
(strExt.IndexOf('?') < 0))
{
strExt = "." + strExt;
foreach(FileInfo fi in v)
{
if(fi == null) { Debug.Assert(false); continue; }
string strPathRaw = fi.FullName;
if(strPathRaw == null) { Debug.Assert(false); continue; }
string strPath = strPathRaw.Trim(m_vPathTrimCharsWs);
if(strPath.Length == 0) { Debug.Assert(false); continue; }
Debug.Assert(strPath == strPathRaw);
if(!strPath.EndsWith(strExt, StrUtil.CaseIgnoreCmp))
continue;
l.Add(fi);
}
}
else l.AddRange(v);
return l;
}
#endif
} }
} }

View File

@@ -1,49 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ModernKeePassLib.WinRTAdaptors
{
// BERT TODO: Whole class is just a non-functional stub
public struct Color
{
public byte A
{
get
{ return 255; }
}
public byte R
{
get
{
return 100;
}
}
public byte G
{
get { return 150; }
}
public byte B
{
get { return 200; }
}
public bool isEmpty
{
get { return false; }
}
public static Color Empty
{
get
{
Color abc;
return abc; }
}
}
}

View File

@@ -522,7 +522,7 @@
] ]
}, },
"Microsoft.NETCore.Platforms/1.1.0": { "Microsoft.NETCore.Platforms/1.1.0": {
"sha512": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==", "sha512": "+XHS7n+M0uDgC28FAzPVRvDG2SvxtkprfAdbd0Cf9Fqa8YgMuXPXvoTB0SW/W/Z6kbuvp0fVeDItXnC9rnL+XA==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -626,7 +626,7 @@
] ]
}, },
"Microsoft.NETCore.Targets/1.1.0": { "Microsoft.NETCore.Targets/1.1.0": {
"sha512": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==", "sha512": "dUUadXhJMY9VZYrGVdJDKzcXsYcUmadCTd1Kz4VQgLuZhaC+QlbC7tDkFSE+snB5TBLxmRU3ZfX8ur4buLawqQ==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -638,7 +638,7 @@
] ]
}, },
"Microsoft.NETCore.Windows.ApiSets/1.0.1": { "Microsoft.NETCore.Windows.ApiSets/1.0.1": {
"sha512": "SaToCvvsGMxTgtLv/BrFQ5IFMPRE1zpWbnqbpwykJa8W5XiX82CXI6K2o7yf5xS7EP6t/JzFLV0SIDuWpvBZVw==", "sha512": "q0mF2juY/56CMT5b+bi8uh90ZiH1DB8TCoaK6nOTRZPQmRiqz+8JuOIu1upvy21SZHoesIl9alCFXK5MlfKFuQ==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -776,7 +776,7 @@
] ]
}, },
"runtime.native.System/4.3.0": { "runtime.native.System/4.3.0": {
"sha512": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", "sha512": "HhykbX7CxJfRxeSnztqdszl4wvsxTi3Q5vhPitlPQt5LKBI6q2cvXrQjBS1FTBgdA3O+rliE86qsDCu1mzLXYg==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -787,7 +787,7 @@
] ]
}, },
"System.Collections/4.3.0": { "System.Collections/4.3.0": {
"sha512": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", "sha512": "odtewSKaGFM1cRV0i2f+fF1wDTcPLisgZVNa1Jrm88mDNAxD52TRh0U51jwqs73RH91GYI4ogCkF9r7W0zVoDw==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -852,7 +852,7 @@
] ]
}, },
"System.Collections.Concurrent/4.3.0": { "System.Collections.Concurrent/4.3.0": {
"sha512": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", "sha512": "574p/+ur5xdbM7fZCoFJLM2pqCO4B843KdXjrxYZC9AGSiDwAtlq90gkgg3xg5YwcDPa/C7Y0Uylh2n7QIZ5nQ==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -917,7 +917,7 @@
] ]
}, },
"System.Diagnostics.Debug/4.3.0": { "System.Diagnostics.Debug/4.3.0": {
"sha512": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", "sha512": "1woBURpg50IpEZZ7BK8AZe1T24GsBY+e6MyEufMAPVMZoVzRDRwejOLLfIIkgY2hgw0bk6CXAFg4dB2iFF5IVQ==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -982,7 +982,7 @@
] ]
}, },
"System.Diagnostics.Tools/4.3.0": { "System.Diagnostics.Tools/4.3.0": {
"sha512": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", "sha512": "cNBqRhfTSwBU0OfXuTvV+sRaE8EfJRYrkh1giN74UvENZb6SHLJw23GroCIrvyV4j03gp0a1028I4dEsRi0XoQ==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -1036,7 +1036,7 @@
] ]
}, },
"System.Diagnostics.Tracing/4.3.0": { "System.Diagnostics.Tracing/4.3.0": {
"sha512": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", "sha512": "sE7+yUZUrkcebditDSxZLnsCwG/oI4RELRdhSmen0ig1AH1kW5b9ztJ7HQbK3sCIuY0Yd5OvqyX0pOie4T35fQ==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -1123,7 +1123,7 @@
] ]
}, },
"System.Globalization/4.3.0": { "System.Globalization/4.3.0": {
"sha512": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", "sha512": "VqCYVd4WTRcRl/U08cJOFmyDFPs79CFfcEbav+p7Q5Sj7Lokf0R+mD0TEc+f8+GVBRtaff6b+mknJnIR44LvYQ==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -1188,7 +1188,7 @@
] ]
}, },
"System.IO/4.3.0": { "System.IO/4.3.0": {
"sha512": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", "sha512": "YsCDVvNbX1fQsiQuBRb7Wy/v+L14iJ0JhzInNXsblcU2wUZ8fD33Q5RBRZ4PUu2iZKQ6KnrfaOxWScxoGcIoPA==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -1266,7 +1266,7 @@
] ]
}, },
"System.IO.Compression/4.3.0": { "System.IO.Compression/4.3.0": {
"sha512": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", "sha512": "+G+M250pfD6KOqeADMPvbO2jPqV0UMtE3YECosM/p5bU0Krytlo0qNBrqtbk7uHJS3kOle5kk3T7zlxd/z/pTA==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -1334,7 +1334,7 @@
] ]
}, },
"System.Linq/4.3.0": { "System.Linq/4.3.0": {
"sha512": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", "sha512": "w9wJuI2T9KXZmY/AS7E4PUVzGPS0jhlx1YlKsgzShgNj6Vk9iN7R8qRwWB2kvD+Ki58cpRwM87fVD5yivijJEg==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -1403,7 +1403,7 @@
] ]
}, },
"System.Linq.Expressions/4.3.0": { "System.Linq.Expressions/4.3.0": {
"sha512": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", "sha512": "EjVvFE83n3Ih05PIJ611aMBS321nFT7FS1yIpcnVHLVB3GqaCWaVPMg7/kklhlohrUPXJ4PS5CeUlIBmXMva8w==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -1484,11 +1484,9 @@
] ]
}, },
"System.Net.Http/4.3.2": { "System.Net.Http/4.3.2": {
"sha512": "y7hv0o0weI0j0mvEcBOdt1F3CAADiWlcw3e54m8TfYiRmBPDIsHElx8QUPDlY4x6yWXKPGN0Z2TuXCTPgkm5WQ==", "sha512": "wMTk4xwcImunKYNGcMC35TFe/8LKBhzc1INgatMHmbGt6hNu3IsxcwpYD8r2zstiv64uKK+GTgfxJ7Lh91Qnqw==",
"type": "package", "type": "package",
"files": [ "files": [
"System.Net.Http.4.3.2.nupkg.sha512",
"System.Net.Http.nuspec",
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
"dotnet_library_license.txt", "dotnet_library_license.txt",
"lib/Xamarinmac20/_._", "lib/Xamarinmac20/_._",
@@ -1519,11 +1517,13 @@
"runtimes/unix/lib/netstandard1.6/System.Net.Http.dll", "runtimes/unix/lib/netstandard1.6/System.Net.Http.dll",
"runtimes/win/lib/net46/System.Net.Http.dll", "runtimes/win/lib/net46/System.Net.Http.dll",
"runtimes/win/lib/netcore50/System.Net.Http.dll", "runtimes/win/lib/netcore50/System.Net.Http.dll",
"runtimes/win/lib/netstandard1.3/System.Net.Http.dll" "runtimes/win/lib/netstandard1.3/System.Net.Http.dll",
"system.net.http.4.3.2.nupkg.sha512",
"system.net.http.nuspec"
] ]
}, },
"System.Net.Primitives/4.3.0": { "System.Net.Primitives/4.3.0": {
"sha512": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", "sha512": "Ds2qmHelD5W4JYm+FOub7/4OWbVWKXXsL4+pVVhZxd3urA9yYI6UFPMEnIbK9mCG7rvoli+PVpbczlcy8H+Jmg==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -1599,7 +1599,7 @@
] ]
}, },
"System.Net.Requests/4.3.0": { "System.Net.Requests/4.3.0": {
"sha512": "OZNUuAs0kDXUzm7U5NZ1ojVta5YFZmgT2yxBqsQ7Eseq5Ahz88LInGRuNLJ/NP2F8W1q7tse1pKDthj3reF5QA==", "sha512": "ZvKLMYR1iGBh3ianvGnqMojG8uLtq1jhviCrojW2QUZEPUYKhB28gtLt5iW51nsvmGhFh1WTHvh9CenMuxzLbQ==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -1679,7 +1679,7 @@
] ]
}, },
"System.ObjectModel/4.3.0": { "System.ObjectModel/4.3.0": {
"sha512": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", "sha512": "yXnz+D4S6l25VS9SuCrS8cyVKWgeAQJ/v2epBlTL1cM+Xs6rx0/6gUAXTTruCZiO1UjrhX56isX8DKL267D5gQ==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -1746,7 +1746,7 @@
] ]
}, },
"System.Reflection/4.3.0": { "System.Reflection/4.3.0": {
"sha512": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", "sha512": "gWKa+cLy5BkkDxp6iuKYNQVNlxir4VYpR7siMIW8vQI7lR9E5PsR+Fmm6h+ZzTCu2XFMf9sNvRYRw727QmJ0fw==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -1824,7 +1824,7 @@
] ]
}, },
"System.Reflection.Extensions/4.3.0": { "System.Reflection.Extensions/4.3.0": {
"sha512": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", "sha512": "MZ0vyVl3i7SpA8hLhKjb8wrJ9s4a/bggVHasDqNrbpbkbyMaaYxi8dUDduh5K7RFAHJaR45BAW7+TMbpoQ7Oqg==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -1878,7 +1878,7 @@
] ]
}, },
"System.Reflection.Primitives/4.3.0": { "System.Reflection.Primitives/4.3.0": {
"sha512": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", "sha512": "QcIJSKt4ksNWnTWkNc7fqdnaARA4or2omXIXVi1hzccV8AixhcW4gVNfpdz/jE1cldDBRSeySM5PbF8M3GUHbA==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -1932,7 +1932,7 @@
] ]
}, },
"System.Resources.ResourceManager/4.3.0": { "System.Resources.ResourceManager/4.3.0": {
"sha512": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", "sha512": "DRxdwZJGYZA+sp8Ht53dvNPr8NLsbBzctIrpbx4UFylYbDsoDQzJwchNarrRnwiIfsZHkXYA3HCKewNr62XiRw==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -1986,7 +1986,7 @@
] ]
}, },
"System.Runtime/4.3.0": { "System.Runtime/4.3.0": {
"sha512": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", "sha512": "a+38DiHlk4UA1NMs7Ty0/izJb/ukQtEhDgoy2xrGppdA/nVOkOC1JtR9HCcYYHfxXxQNNsjQ66NNvrbM3oVTrw==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -2075,7 +2075,7 @@
] ]
}, },
"System.Runtime.Extensions/4.3.0": { "System.Runtime.Extensions/4.3.0": {
"sha512": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", "sha512": "P78VOZ2fZUq3otcfcf+6zd+EhWijXhI/BWk/wd9RnWFAddhO4hnlpiqxAIw1yPTZJSWRG5VboYyUmB8xcmcHpQ==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -2153,7 +2153,7 @@
] ]
}, },
"System.Runtime.InteropServices/4.3.0": { "System.Runtime.InteropServices/4.3.0": {
"sha512": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", "sha512": "6CC8BIjVaMtHM3OvOOO0cirqqF6CNluOPtc/DNBkieZhMiz676cszc5ciNCiIWcTcNW+Mb0Cs8LWZrhK7W+rdQ==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -2243,7 +2243,7 @@
] ]
}, },
"System.Runtime.InteropServices.RuntimeInformation/4.3.0": { "System.Runtime.InteropServices.RuntimeInformation/4.3.0": {
"sha512": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", "sha512": "rf6Ebmg9wgokWKK14uiVNdyBY7g4yLaZ4edbiE6XcNX5fyqtgHZTKuP2MFkkzQWL9NGX2LSIfodKQNVnOM+qCA==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -2275,7 +2275,7 @@
] ]
}, },
"System.Runtime.Numerics/4.3.0": { "System.Runtime.Numerics/4.3.0": {
"sha512": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", "sha512": "H73WuUWJAH5UQE1MIxWLdqg+skdOBBwGA+fLu4JgPHJ+0tivNLBrN4TQdJGDvVeGPxrN229R5muocedVVAIfbA==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -2382,7 +2382,7 @@
] ]
}, },
"System.Text.Encoding/4.3.0": { "System.Text.Encoding/4.3.0": {
"sha512": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", "sha512": "3hnC4XGk/ip1HnQuDpA5L3aOsYXSl4I7OlwSb40WlTIEVtOP9VrcqPN4kuT2L3a1kXXr8emjPePQcbtYVjRvjw==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -2447,7 +2447,7 @@
] ]
}, },
"System.Text.Encoding.Extensions/4.3.0": { "System.Text.Encoding.Extensions/4.3.0": {
"sha512": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", "sha512": "q9p8y7bgIQR7IQJQBeOL3TT4H0vg634anhTKgbao9gHvFmmGJkJF6eNhX6Tfcu5vFbKqd+I1+kW/6hVdZXqPmQ==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -2512,7 +2512,7 @@
] ]
}, },
"System.Text.RegularExpressions/4.3.0": { "System.Text.RegularExpressions/4.3.0": {
"sha512": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", "sha512": "SJ9qrjcnDx6YwpMpIgeKL1K/4/uDAHCT6Id3aey/z66H9SIX8PcG2TQ+gYNg7VGm7tI0wkLsV+8dMxbxTam7Yw==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -2593,7 +2593,7 @@
] ]
}, },
"System.Threading/4.3.0": { "System.Threading/4.3.0": {
"sha512": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", "sha512": "cm4+iLU+Gvodk221rboVLwWguLuPOl/bkcCtr+k9hc4tvngnw/dJaoUPqIEsU/FWcCusXk4po3ydFxmRp2lXyw==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -2661,7 +2661,7 @@
] ]
}, },
"System.Threading.Tasks/4.3.0": { "System.Threading.Tasks/4.3.0": {
"sha512": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", "sha512": "1je8yxoIxd0iVjfJbb9DXNIfTt6ESMRIwNwoaB0WhxSfJMLOhfJ3mb9UQsa6Q/98g6jEOyFdSAbr+fPEgwbKUg==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -2726,7 +2726,7 @@
] ]
}, },
"System.Threading.Timer/4.3.0": { "System.Threading.Timer/4.3.0": {
"sha512": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", "sha512": "BzzEELyI/Jct8o0jOeXisFR5uawc5yhFVlgboaxWWWV/Fjahi/ESRRaHlR1HMWAyZsNnybq7v57YgWTVd+NAkg==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -2778,7 +2778,7 @@
] ]
}, },
"System.Xml.ReaderWriter/4.3.0": { "System.Xml.ReaderWriter/4.3.0": {
"sha512": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", "sha512": "41StQbCnhTjv/daEuN55cqY4rUYP1NQI9a8cQktBxDbF5QLFsIvcr9mIFGQ2nrzrk3DYHKwpJ9AkVuMiYymtHg==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",
@@ -2847,7 +2847,7 @@
] ]
}, },
"System.Xml.XDocument/4.3.0": { "System.Xml.XDocument/4.3.0": {
"sha512": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", "sha512": "WT8lBJSEINzk3c9dm3n0vlqb9Z9PoORD29n/rbkcNh3feSZTJeYQ5+xgSbJhdsyvpmsRsE56fdsH4fchJt65PQ==",
"type": "package", "type": "package",
"files": [ "files": [
"ThirdPartyNotices.txt", "ThirdPartyNotices.txt",