WIP KeePassLibPCL - problem with awaitables

This commit is contained in:
2017-09-22 18:48:09 +02:00
parent a43bc20eb3
commit 668afbe817
108 changed files with 1205 additions and 4203 deletions

View File

@@ -22,103 +22,105 @@ using System.Text;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Security.Cryptography.Core;
using Windows.Security.ExchangeActiveSyncProvisioning;
#if PCL
using Windows.Security.Cryptography;
#if ModernKeePassLibPCL
using PCLCrypto;
#else
using System.Security.Cryptography;
#endif
using ModernKeePassLib.Resources;
using ModernKeePassLib.Security;
using ModernKeePassLib.Utility;
#if KeePassRT
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
#endif
namespace ModernKeePassLib.Keys
using ModernKeePassLibPCL.Native;
using ModernKeePassLibPCL.Resources;
using ModernKeePassLibPCL.Security;
using ModernKeePassLibPCL.Utility;
namespace ModernKeePassLibPCL.Keys
{
/// <summary>
/// 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,
/// the current computer ID, etc.
/// </summary>
public sealed class CompositeKey
{
private List<IUserKey> m_vUserKeys = new List<IUserKey>();
/// <summary>
/// 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,
/// the current computer ID, etc.
/// </summary>
public sealed class CompositeKey
{
private List<IUserKey> m_vUserKeys = new List<IUserKey>();
/// <summary>
/// List of all user keys contained in the current composite key.
/// </summary>
public IEnumerable<IUserKey> UserKeys
{
get { return m_vUserKeys; }
}
/// <summary>
/// List of all user keys contained in the current composite key.
/// </summary>
public IEnumerable<IUserKey> UserKeys
{
get { return m_vUserKeys; }
}
public uint UserKeyCount
{
get { return (uint) m_vUserKeys.Count; }
}
public uint UserKeyCount
{
get { return (uint)m_vUserKeys.Count; }
}
/// <summary>
/// Construct a new, empty key object.
/// </summary>
public CompositeKey()
{
}
/// <summary>
/// Construct a new, empty key object.
/// </summary>
public CompositeKey()
{
}
// /// <summary>
// /// Deconstructor, clears up the key.
// /// </summary>
// ~CompositeKey()
// {
// Clear();
// }
// /// <summary>
// /// Deconstructor, clears up the key.
// /// </summary>
// ~CompositeKey()
// {
// Clear();
// }
// /// <summary>
// /// Clears the key. This function also erases all previously stored
// /// user key data objects.
// /// </summary>
// public void Clear()
// {
// foreach(IUserKey pKey in m_vUserKeys)
// pKey.Clear();
// m_vUserKeys.Clear();
// }
// /// <summary>
// /// Clears the key. This function also erases all previously stored
// /// user key data objects.
// /// </summary>
// public void Clear()
// {
// foreach(IUserKey pKey in m_vUserKeys)
// pKey.Clear();
// m_vUserKeys.Clear();
// }
/// <summary>
/// Add a user key.
/// </summary>
/// <param name="pKey">User key to add.</param>
public void AddUserKey(IUserKey pKey)
{
Debug.Assert(pKey != null);
if (pKey == null) throw new ArgumentNullException("pKey");
/// <summary>
/// Add a user key.
/// </summary>
/// <param name="pKey">User key to add.</param>
public void AddUserKey(IUserKey pKey)
{
Debug.Assert(pKey != null); if(pKey == null) throw new ArgumentNullException("pKey");
m_vUserKeys.Add(pKey);
}
m_vUserKeys.Add(pKey);
}
/// <summary>
/// Remove a user key.
/// </summary>
/// <param name="pKey">User key to remove.</param>
/// <returns>Returns <c>true</c> if the key was removed successfully.</returns>
public bool RemoveUserKey(IUserKey pKey)
{
Debug.Assert(pKey != null);
if (pKey == null) throw new ArgumentNullException("pKey");
/// <summary>
/// Remove a user key.
/// </summary>
/// <param name="pKey">User key to remove.</param>
/// <returns>Returns <c>true</c> if the key was removed successfully.</returns>
public bool RemoveUserKey(IUserKey pKey)
{
Debug.Assert(pKey != null); if(pKey == null) throw new ArgumentNullException("pKey");
Debug.Assert(m_vUserKeys.IndexOf(pKey) >= 0);
return m_vUserKeys.Remove(pKey);
}
Debug.Assert(m_vUserKeys.IndexOf(pKey) >= 0);
return m_vUserKeys.Remove(pKey);
}
#if !PCL && !KeePassRT /// <summary>
/// Test whether the composite key contains a specific type of
/// user keys (password, key file, ...). If at least one user
/// key of that type is present, the function returns <c>true</c>.
/// </summary>
/// <param name="tUserKeyType">User key type.</param>
/// <returns>Returns <c>true</c>, if the composite key contains
/// a user key of the specified type.</returns>
#if !ModernKeePassLibPCL && !KeePassRT
/// <summary>
/// Test whether the composite key contains a specific type of
/// user keys (password, key file, ...). If at least one user
/// key of that type is present, the function returns <c>true</c>.
/// </summary>
/// <param name="tUserKeyType">User key type.</param>
/// <returns>Returns <c>true</c>, if the composite key contains
/// a user key of the specified type.</returns>
public bool ContainsType(Type tUserKeyType)
{
Debug.Assert(tUserKeyType != null);
@@ -154,91 +156,85 @@ namespace ModernKeePassLib.Keys
}
#endif
/// <summary>
/// Creates the composite key from the supplied user key sources (password,
/// key file, user account, computer ID, etc.).
/// </summary>
private byte[] CreateRawCompositeKey32()
{
ValidateUserKeys();
/// <summary>
/// Creates the composite key from the supplied user key sources (password,
/// key file, user account, computer ID, etc.).
/// </summary>
private byte[] CreateRawCompositeKey32()
{
ValidateUserKeys();
// Concatenate user key data
MemoryStream ms = new MemoryStream();
foreach (IUserKey pKey in m_vUserKeys)
{
ProtectedBinary b = pKey.KeyData;
if (b != null)
{
byte[] pbKeyData = b.ReadData();
ms.Write(pbKeyData, 0, pbKeyData.Length);
MemUtil.ZeroByteArray(pbKeyData);
}
}
// Concatenate user key data
MemoryStream ms = new MemoryStream();
foreach(IUserKey pKey in m_vUserKeys)
{
ProtectedBinary b = pKey.KeyData;
if(b != null)
{
byte[] pbKeyData = b.ReadData();
ms.Write(pbKeyData, 0, pbKeyData.Length);
MemUtil.ZeroByteArray(pbKeyData);
}
}
#if PCL
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
var pbHash = sha256.HashData(ms.ToArray().AsBuffer()).ToArray();
#if ModernKeePassLibPCL
var sha256 = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(HashAlgorithm.Sha256);
var pbHash = sha256.HashData(ms.ToArray());
#else
SHA256Managed sha256 = new SHA256Managed();
byte[] pbHash = sha256.ComputeHash(ms.ToArray());
#endif
ms.Dispose();
return pbHash;
}
ms.Dispose();
return pbHash;
}
public bool EqualsValue(CompositeKey ckOther)
{
if (ckOther == null) throw new ArgumentNullException("ckOther");
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);
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);
return bResult;
}
return bResult;
}
/// <summary>
/// Generate a 32-bit wide key out of the composite key.
/// </summary>
/// <param name="pbKeySeed32">Seed used in the key transformation
/// 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");
/// <summary>
/// Generate a 32-bit wide key out of the composite key.
/// </summary>
/// <param name="pbKeySeed32">Seed used in the key transformation
/// 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");
byte[] pbRaw32 = CreateRawCompositeKey32();
if ((pbRaw32 == null) || (pbRaw32.Length != 32))
{
Debug.Assert(false);
return null;
}
byte[] pbRaw32 = CreateRawCompositeKey32();
if((pbRaw32 == null) || (pbRaw32.Length != 32))
{ Debug.Assert(false); return null; }
byte[] pbTrf32 = TransformKey(pbRaw32, pbKeySeed32, uNumRounds);
if ((pbTrf32 == null) || (pbTrf32.Length != 32))
{
Debug.Assert(false);
return null;
}
byte[] pbTrf32 = TransformKey(pbRaw32, pbKeySeed32, uNumRounds);
if((pbTrf32 == null) || (pbTrf32.Length != 32))
{ Debug.Assert(false); return null; }
ProtectedBinary pbRet = new ProtectedBinary(true, pbTrf32);
MemUtil.ZeroByteArray(pbTrf32);
MemUtil.ZeroByteArray(pbRaw32);
ProtectedBinary pbRet = new ProtectedBinary(true, pbTrf32);
MemUtil.ZeroByteArray(pbTrf32);
MemUtil.ZeroByteArray(pbRaw32);
return pbRet;
}
return pbRet;
}
private void ValidateUserKeys()
{
#if !PCL
private void ValidateUserKeys()
{
#if !ModernKeePassLibPCL
int nAccounts = 0;
foreach(IUserKey uKey in m_vUserKeys)
@@ -253,51 +249,52 @@ namespace ModernKeePassLib.Keys
throw new InvalidOperationException();
}
#endif
}
}
/// <summary>
/// Transform the current key <c>uNumRounds</c> times.
/// </summary>
/// <param name="pbOriginalKey32">The original key which will be transformed.
/// This parameter won't be modified.</param>
/// <param name="pbKeySeed32">Seed used for key transformations. Must not
/// be <c>null</c>. This parameter won't be modified.</param>
/// <param name="uNumRounds">Transformation count.</param>
/// <returns>256-bit transformed key.</returns>
private static byte[] TransformKey(byte[] pbOriginalKey32, byte[] pbKeySeed32,
ulong uNumRounds)
{
Debug.Assert((pbOriginalKey32 != null) && (pbOriginalKey32.Length == 32));
if (pbOriginalKey32 == null) throw new ArgumentNullException("pbOriginalKey32");
if (pbOriginalKey32.Length != 32) throw new ArgumentException();
/// <summary>
/// Transform the current key <c>uNumRounds</c> times.
/// </summary>
/// <param name="pbOriginalKey32">The original key which will be transformed.
/// This parameter won't be modified.</param>
/// <param name="pbKeySeed32">Seed used for key transformations. Must not
/// be <c>null</c>. This parameter won't be modified.</param>
/// <param name="uNumRounds">Transformation count.</param>
/// <returns>256-bit transformed key.</returns>
private static byte[] TransformKey(byte[] pbOriginalKey32, byte[] pbKeySeed32,
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((pbKeySeed32 != null) && (pbKeySeed32.Length == 32));
if (pbKeySeed32 == null) throw new ArgumentNullException("pbKeySeed32");
if (pbKeySeed32.Length != 32) throw new ArgumentException();
Debug.Assert((pbKeySeed32 != null) && (pbKeySeed32.Length == 32));
if(pbKeySeed32 == null) throw new ArgumentNullException("pbKeySeed32");
if(pbKeySeed32.Length != 32) throw new ArgumentException();
byte[] pbNewKey = new byte[32];
Array.Copy(pbOriginalKey32, pbNewKey, pbNewKey.Length);
byte[] pbNewKey = new byte[32];
Array.Copy(pbOriginalKey32, pbNewKey, pbNewKey.Length);
#if !PCL // Try to use the native library first
#if !ModernKeePassLibPCL
// Try to use the native library first
if(NativeLib.TransformKey256(pbNewKey, pbKeySeed32, uNumRounds))
return (new SHA256Managed()).ComputeHash(pbNewKey);
#endif
if (TransformKeyManaged(pbNewKey, pbKeySeed32, uNumRounds) == false)
return null;
if(TransformKeyManaged(pbNewKey, pbKeySeed32, uNumRounds) == false)
return null;
#if PCL
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
return sha256.HashData(pbNewKey.AsBuffer()).ToArray();
#if ModernKeePassLibPCL
var sha256 = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(HashAlgorithm.Sha256);
return sha256.HashData(pbNewKey);
#else
SHA256Managed sha256 = new SHA256Managed();
return sha256.ComputeHash(pbNewKey);
#endif
}
}
public static bool TransformKeyManaged(byte[] pbNewKey32, byte[] pbKeySeed32,
ulong uNumRounds)
{
public static bool TransformKeyManaged(byte[] pbNewKey32, byte[] pbKeySeed32,
ulong uNumRounds)
{
#if KeePassRT
KeyParameter kp = new KeyParameter(pbKeySeed32);
AesEngine aes = new AesEngine();
@@ -308,10 +305,11 @@ namespace ModernKeePassLib.Keys
aes.ProcessBlock(pbNewKey32, 0, pbNewKey32, 0);
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
#if ModernKeePassLibPCL
var aes = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesEcb);
var key = aes.CreateSymmetricKey(pbKeySeed32);
var iCrypt = WinRTCrypto.CryptographicEngine.CreateEncryptor(key);
#else
byte[] pbIV = new byte[16];
Array.Clear(pbIV, 0, pbIV.Length);
@@ -330,29 +328,125 @@ namespace ModernKeePassLib.Keys
ICryptoTransform iCrypt = r.CreateEncryptor();
#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;
}
// !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 false;
}
for (ulong i = 0; i < uNumRounds; ++i)
{
/*iCrypt.TransformBlock(pbNewKey32, 0, 16, pbNewKey32, 0);
iCrypt.TransformBlock(pbNewKey32, 16, 16, pbNewKey32, 16);*/
}
for(ulong i = 0; i < uNumRounds; ++i)
{
iCrypt.TransformBlock(pbNewKey32, 0, 16, pbNewKey32, 0);
iCrypt.TransformBlock(pbNewKey32, 16, 16, pbNewKey32, 16);
}
#endif
return true;
}
}
return true;
}
public sealed class InvalidCompositeKeyException : Exception
/// <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)
{
ulong uRounds;
#if !ModernKeePassLibPCL
// Try native method
if(NativeLib.TransformKeyBenchmark256(uMilliseconds, out uRounds))
return uRounds;
#endif
byte[] pbKey = new byte[32];
byte[] pbNewKey = new byte[32];
for(int i = 0; i < pbKey.Length; ++i)
{
pbKey[i] = (byte)i;
pbNewKey[i] = (byte)i;
}
#if KeePassRT
KeyParameter kp = new KeyParameter(pbKey);
AesEngine aes = new AesEngine();
aes.Init(true, kp);
#else
#if ModernKeePassLibPCL
var aes = WinRTCrypto.SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithm.AesEcb);
var key = aes.CreateSymmetricKey(pbKey);
var iCrypt = WinRTCrypto.CryptographicEngine.CreateEncryptor(key);
#else
byte[] pbIV = new byte[16];
Array.Clear(pbIV, 0, pbIV.Length);
RijndaelManaged r = new RijndaelManaged();
if(r.BlockSize != 128) // AES block size
{
Debug.Assert(false);
r.BlockSize = 128;
}
r.IV = pbIV;
r.Mode = CipherMode.ECB;
r.KeySize = 256;
r.Key = pbKey;
ICryptoTransform iCrypt = r.CreateEncryptor();
#endif
// !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;
}
#endif
uRounds = 0;
int tStart = Environment.TickCount;
while(true)
{
for(ulong j = 0; j < uStep; ++j)
{
#if KeePassRT
aes.ProcessBlock(pbNewKey, 0, pbNewKey, 0);
aes.ProcessBlock(pbNewKey, 16, pbNewKey, 16);
#else
iCrypt.TransformBlock(pbNewKey, 0, 16, pbNewKey, 0);
iCrypt.TransformBlock(pbNewKey, 16, 16, pbNewKey, 16);
#endif
}
uRounds += uStep;
if(uRounds < uStep) // Overflow check
{
uRounds = ulong.MaxValue;
break;
}
uint tElapsed = (uint)(Environment.TickCount - tStart);
if(tElapsed > uMilliseconds) break;
}
return uRounds;
}
}
public sealed class InvalidCompositeKeyException : Exception
{
public override string Message
{

View File

@@ -19,9 +19,9 @@
using System;
using ModernKeePassLib.Security;
using ModernKeePassLibPCL.Security;
namespace ModernKeePassLib.Keys
namespace ModernKeePassLibPCL.Keys
{
/// <summary>
/// Interface to a user key, like a password, key file data, etc.

View File

@@ -21,18 +21,16 @@ 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;
#if ModernKeePassLibPCL
using PCLCrypto;
#else
using System.Security.Cryptography;
#endif
using ModernKeePassLib.Security;
using ModernKeePassLib.Utility;
using ModernKeePassLibPCL.Security;
using ModernKeePassLibPCL.Utility;
namespace ModernKeePassLib.Keys
namespace ModernKeePassLibPCL.Keys
{
public sealed class KcpCustomKey : IUserKey
{
@@ -61,14 +59,14 @@ namespace ModernKeePassLib.Keys
if(bPerformHash)
{
#if PCL
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
var pbRaw = sha256.HashData(pbKeyData.AsBuffer());
#if ModernKeePassLibPCL
var sha256 = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(HashAlgorithm.Sha256);
var pbRaw = sha256.HashData(pbKeyData);
#else
SHA256Managed sha256 = new SHA256Managed();
byte[] pbRaw = sha256.ComputeHash(pbKeyData);
#endif
m_pbKey = new ProtectedBinary(true, pbRaw.ToArray());
m_pbKey = new ProtectedBinary(true, pbRaw);
}
else m_pbKey = new ProtectedBinary(true, pbKeyData);
}

View File

@@ -22,24 +22,23 @@ using System.Text;
using System.IO;
using System.Xml;
using System.Security;
#if PCL
#if ModernKeePassLibPCL
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Windows.Security.Cryptography;
using PCLCrypto;
#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.Serialization;
using ModernKeePassLib.Utility;
namespace ModernKeePassLib.Keys
using ModernKeePassLibPCL.Cryptography;
using ModernKeePassLibPCL.Resources;
using ModernKeePassLibPCL.Security;
using ModernKeePassLibPCL.Serialization;
using ModernKeePassLibPCL.Utility;
namespace ModernKeePassLibPCL.Keys
{
/// <summary>
/// Key files as provided by the user.
@@ -139,9 +138,9 @@ namespace ModernKeePassLib.Keys
if(pbKey == null)
{
#if PCL
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
pbKey = sha256.HashData(pbFileData.AsBuffer()).ToArray();
#if ModernKeePassLibPCL
var sha256 = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(HashAlgorithm.Sha256);
pbKey = sha256.HashData(pbFileData);
#else
SHA256Managed sha256 = new SHA256Managed();
pbKey = sha256.ComputeHash(pbFileData);
@@ -199,19 +198,18 @@ namespace ModernKeePassLib.Keys
pbFinalKey32 = pbKey32;
else
{
using (MemoryStream ms = new MemoryStream())
{
ms.Write(pbAdditionalEntropy, 0, pbAdditionalEntropy.Length);
ms.Write(pbKey32, 0, 32);
MemoryStream ms = new MemoryStream();
ms.Write(pbAdditionalEntropy, 0, pbAdditionalEntropy.Length);
ms.Write(pbKey32, 0, 32);
#if PCL
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
pbFinalKey32 = sha256.HashData(ms.GetWindowsRuntimeBuffer()).ToArray();
#if ModernKeePassLibPCL
var sha256 = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(HashAlgorithm.Sha256);
pbFinalKey32 = sha256.HashData(ms.ToArray());
#else
SHA256Managed sha256 = new SHA256Managed();
pbFinalKey32 = sha256.ComputeHash(ms.ToArray());
SHA256Managed sha256 = new SHA256Managed();
pbFinalKey32 = sha256.ComputeHash(ms.ToArray());
#endif
}
ms.Dispose();
}
CreateXmlKeyFile(strFilePath, pbFinalKey32);
@@ -247,7 +245,7 @@ namespace ModernKeePassLib.Keys
try
{
#if PCL
#if ModernKeePassLibPCL
var doc = XDocument.Load(ms);
@@ -315,7 +313,7 @@ namespace ModernKeePassLib.Keys
IOConnectionInfo ioc = IOConnectionInfo.FromPath(strFile);
Stream sOut = IOConnection.OpenWrite(ioc);
#if PCL
#if ModernKeePassLibPCL
var settings = new XmlWriterSettings() { Encoding = StrUtil.Utf8 };
var xtw = XmlWriter.Create(sOut, settings);
#else

View File

@@ -20,18 +20,16 @@
using System;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Security.Cryptography.Core;
#if PCL
using Windows.Security.Cryptography;
#if ModernKeePassLibPCL
using PCLCrypto;
#else
using System.Security.Cryptography;
#endif
using ModernKeePassLib.Security;
using ModernKeePassLib.Utility;
using ModernKeePassLibPCL.Security;
using ModernKeePassLibPCL.Utility;
namespace ModernKeePassLib.Keys
namespace ModernKeePassLibPCL.Keys
{
/// <summary>
/// Master password / passphrase as provided by the user.
@@ -74,16 +72,16 @@ namespace ModernKeePassLib.Keys
Debug.Assert(pbPasswordUtf8 != null);
if(pbPasswordUtf8 == null) throw new ArgumentNullException("pbPasswordUtf8");
#if PCL
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
var pbRaw = sha256.HashData(pbPasswordUtf8.AsBuffer());
#if ModernKeePassLibPCL
var sha256 = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(HashAlgorithm.Sha256);
var pbRaw = sha256.HashData(pbPasswordUtf8);
#else
SHA256Managed sha256 = new SHA256Managed();
byte[] pbRaw = sha256.ComputeHash(pbPasswordUtf8);
#endif
m_psPassword = new ProtectedString(true, pbPasswordUtf8);
m_pbKeyData = new ProtectedBinary(true, pbRaw.ToArray());
m_pbKeyData = new ProtectedBinary(true, pbRaw);
}
// public void Clear()

View File

@@ -19,18 +19,15 @@
using System;
using System.Security;
using Windows.Security.Cryptography;
using System.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.Utility;
namespace ModernKeePassLib.Keys
using ModernKeePassLibPCL.Cryptography;
using ModernKeePassLibPCL.Resources;
using ModernKeePassLibPCL.Security;
using ModernKeePassLibPCL.Utility;
namespace ModernKeePassLibPCL.Keys
{
/// <summary>
/// A user key depending on the currently logged on Windows user account.
@@ -65,11 +62,8 @@ namespace ModernKeePassLib.Keys
// Test if ProtectedData is supported -- throws an exception
// when running on an old system (Windows 98 / ME).
byte[] pbDummyData = new byte[128];
DataProtectionProvider provider = new DataProtectionProvider("Local=user");
provider.ProtectAsync(pbDummyData.AsBuffer()).GetResults();
/*ProtectedData.Protect(pbDummyData, m_pbEntropy,
DataProtectionScope.CurrentUser);*/
ProtectedData.Protect(pbDummyData, m_pbEntropy,
DataProtectionScope.CurrentUser);
byte[] pbKey = LoadUserKey(false);
if(pbKey == null) pbKey = CreateUserKey();
@@ -87,19 +81,17 @@ namespace ModernKeePassLib.Keys
private static string GetUserKeyFilePath(bool bCreate)
{
#if KeePassRT
string strUserDir = ApplicationData.Current.RoamingFolder.Path;
string strUserDir = Windows.Storage.ApplicationData.Current.RoamingFolder.Path;
#else
/*string strUserDir = Environment.GetFolderPath(
Environment.SpecialFolder.ApplicationData);*/
var strUserDir = ApplicationData.Current.RoamingFolder.Path;
string strUserDir = Environment.GetFolderPath(
Environment.SpecialFolder.ApplicationData);
#endif
strUserDir = UrlUtil.EnsureTerminatingSeparator(strUserDir, false);
strUserDir += PwDefs.ShortProductName;
// Folder is sure to exist
/*if(bCreate && !Directory.Exists(strUserDir))
Directory.CreateDirectory(strUserDir);*/
if(bCreate && !Directory.Exists(strUserDir))
Directory.CreateDirectory(strUserDir);
strUserDir = UrlUtil.EnsureTerminatingSeparator(strUserDir, false);
return strUserDir + UserKeyFileName;
@@ -113,27 +105,16 @@ namespace ModernKeePassLib.Keys
try
{
string strFilePath = GetUserKeyFilePath(false);
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();
byte[] pbProtectedKey = File.ReadAllBytes(strFilePath);
//byte[] pbProtectedKey = File.ReadAllBytes(strFilePath);
pbKey = ProtectedData.Unprotect(pbProtectedKey, m_pbEntropy,
DataProtectionScope.CurrentUser);
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);
}
Array.Clear(pbProtectedKey, 0, pbProtectedKey.Length);
}
catch(Exception exLoad)
{
//if(bShowWarning) MessageService.ShowWarning(exLoad);
if(bShowWarning) MessageService.ShowWarning(exLoad);
pbKey = null;
}
@@ -152,16 +133,10 @@ namespace ModernKeePassLib.Keys
string strFilePath = GetUserKeyFilePath(true);
byte[] pbRandomKey = CryptoRandom.Instance.GetRandomBytes(64);
byte[] pbProtectedKey = ProtectedData.Protect(pbRandomKey,
m_pbEntropy, DataProtectionScope.CurrentUser);
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);
File.WriteAllBytes(strFilePath, pbProtectedKey);
Array.Clear(pbProtectedKey, 0, pbProtectedKey.Length);
Array.Clear(pbRandomKey, 0, pbRandomKey.Length);

View File

@@ -21,9 +21,9 @@ using System;
using System.Collections.Generic;
using System.Text;
using ModernKeePassLib.Serialization;
using ModernKeePassLibPCL.Serialization;
namespace ModernKeePassLib.Keys
namespace ModernKeePassLibPCL.Keys
{
public sealed class KeyProviderQueryContext
{

View File

@@ -23,7 +23,7 @@ using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
namespace ModernKeePassLib.Keys
namespace ModernKeePassLibPCL.Keys
{
public sealed class KeyProviderPool : IEnumerable<KeyProvider>
{

View File

@@ -21,7 +21,7 @@ using System;
using System.Collections.Generic;
using System.Text;
namespace ModernKeePassLib.Keys
namespace ModernKeePassLibPCL.Keys
{
public enum KeyValidationType
{

View File

@@ -23,9 +23,9 @@ using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using ModernKeePassLib.Utility;
using ModernKeePassLibPCL.Utility;
namespace ModernKeePassLib.Keys
namespace ModernKeePassLibPCL.Keys
{
public sealed class KeyValidatorPool : IEnumerable<KeyValidator>
{

View File

@@ -19,7 +19,7 @@
using System;
namespace ModernKeePassLib.Keys
namespace ModernKeePassLibPCL.Keys
{
[Flags]
public enum UserKeyType