mirror of
https://github.com/wismna/ModernKeePassLib.git
synced 2025-10-03 15:40:20 -04:00
Setup solution
This commit is contained in:
295
ModernKeePassLib/Keys/CompositeKey.cs
Normal file
295
ModernKeePassLib/Keys/CompositeKey.cs
Normal file
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2019 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.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
using ModernKeePassLib.Cryptography;
|
||||
using ModernKeePassLib.Cryptography.KeyDerivation;
|
||||
using ModernKeePassLib.Resources;
|
||||
using ModernKeePassLib.Security;
|
||||
using ModernKeePassLib.Utility;
|
||||
|
||||
namespace ModernKeePassLib.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>
|
||||
/// 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; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new, empty key object.
|
||||
/// </summary>
|
||||
public CompositeKey()
|
||||
{
|
||||
}
|
||||
|
||||
// /// <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>
|
||||
/// 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);
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
|
||||
/// <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);
|
||||
if(tUserKeyType == null) throw new ArgumentNullException("tUserKeyType");
|
||||
|
||||
foreach(IUserKey pKey in m_vUserKeys)
|
||||
{
|
||||
if(pKey == null) { Debug.Assert(false); continue; }
|
||||
|
||||
#if KeePassUAP
|
||||
if(pKey.GetType() == tUserKeyType)
|
||||
return true;
|
||||
#else
|
||||
if(tUserKeyType.IsInstanceOfType(pKey))
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the first user key of a specified type.
|
||||
/// </summary>
|
||||
/// <param name="tUserKeyType">Type of the user key to get.</param>
|
||||
/// <returns>Returns the first user key of the specified type
|
||||
/// or <c>null</c> if no key of that type is found.</returns>
|
||||
public IUserKey GetUserKey(Type tUserKeyType)
|
||||
{
|
||||
Debug.Assert(tUserKeyType != null);
|
||||
if(tUserKeyType == null) throw new ArgumentNullException("tUserKeyType");
|
||||
|
||||
foreach(IUserKey pKey in m_vUserKeys)
|
||||
{
|
||||
if(pKey == null) { Debug.Assert(false); continue; }
|
||||
|
||||
#if KeePassUAP
|
||||
if(pKey.GetType() == tUserKeyType)
|
||||
return pKey;
|
||||
#else
|
||||
if(tUserKeyType.IsInstanceOfType(pKey))
|
||||
return pKey;
|
||||
#endif
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <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
|
||||
List<byte[]> lData = new List<byte[]>();
|
||||
int cbData = 0;
|
||||
foreach(IUserKey pKey in m_vUserKeys)
|
||||
{
|
||||
ProtectedBinary b = pKey.KeyData;
|
||||
if(b != null)
|
||||
{
|
||||
byte[] pbKeyData = b.ReadData();
|
||||
lData.Add(pbKeyData);
|
||||
cbData += pbKeyData.Length;
|
||||
}
|
||||
}
|
||||
|
||||
byte[] pbAllData = new byte[cbData];
|
||||
int p = 0;
|
||||
foreach(byte[] pbData in lData)
|
||||
{
|
||||
Array.Copy(pbData, 0, pbAllData, p, pbData.Length);
|
||||
p += pbData.Length;
|
||||
MemUtil.ZeroByteArray(pbData);
|
||||
}
|
||||
Debug.Assert(p == cbData);
|
||||
|
||||
byte[] pbHash = CryptoUtil.HashSha256(pbAllData);
|
||||
MemUtil.ZeroByteArray(pbAllData);
|
||||
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);
|
||||
MemUtil.ZeroByteArray(pbOther);
|
||||
MemUtil.ZeroByteArray(pbThis);
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
[Obsolete]
|
||||
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");
|
||||
|
||||
AesKdf kdf = new AesKdf();
|
||||
KdfParameters p = kdf.GetDefaultParameters();
|
||||
p.SetUInt64(AesKdf.ParamRounds, uNumRounds);
|
||||
p.SetByteArray(AesKdf.ParamSeed, pbKeySeed32);
|
||||
|
||||
return GenerateKey32(p);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a 32-byte (256-bit) key from the composite key.
|
||||
/// </summary>
|
||||
public ProtectedBinary GenerateKey32(KdfParameters p)
|
||||
{
|
||||
if(p == null) { Debug.Assert(false); throw new ArgumentNullException("p"); }
|
||||
|
||||
byte[] pbRaw32 = CreateRawCompositeKey32();
|
||||
if((pbRaw32 == null) || (pbRaw32.Length != 32))
|
||||
{ Debug.Assert(false); return null; }
|
||||
|
||||
KdfEngine kdf = KdfPool.Get(p.KdfUuid);
|
||||
if(kdf == null) // CryptographicExceptions are translated to "file corrupted"
|
||||
throw new Exception(KLRes.UnknownKdf + MessageService.NewParagraph +
|
||||
KLRes.FileNewVerOrPlgReq + MessageService.NewParagraph +
|
||||
"UUID: " + p.KdfUuid.ToHexString() + ".");
|
||||
|
||||
byte[] pbTrf32 = kdf.Transform(pbRaw32, p);
|
||||
if(pbTrf32 == null) { Debug.Assert(false); return null; }
|
||||
|
||||
if(pbTrf32.Length != 32)
|
||||
{
|
||||
Debug.Assert(false);
|
||||
pbTrf32 = CryptoUtil.HashSha256(pbTrf32);
|
||||
}
|
||||
|
||||
ProtectedBinary pbRet = new ProtectedBinary(true, pbTrf32);
|
||||
MemUtil.ZeroByteArray(pbTrf32);
|
||||
MemUtil.ZeroByteArray(pbRaw32);
|
||||
return pbRet;
|
||||
}
|
||||
|
||||
private void ValidateUserKeys()
|
||||
{
|
||||
int nAccounts = 0;
|
||||
|
||||
foreach(IUserKey uKey in m_vUserKeys)
|
||||
{
|
||||
if(uKey is KcpUserAccount)
|
||||
++nAccounts;
|
||||
}
|
||||
|
||||
if(nAccounts >= 2)
|
||||
{
|
||||
Debug.Assert(false);
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class InvalidCompositeKeyException : Exception
|
||||
{
|
||||
public override string Message
|
||||
{
|
||||
get
|
||||
{
|
||||
return KLRes.InvalidCompositeKey + MessageService.NewParagraph +
|
||||
KLRes.InvalidCompositeKeyHint;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new invalid composite key exception.
|
||||
/// </summary>
|
||||
public InvalidCompositeKeyException()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
46
ModernKeePassLib/Keys/IUserKey.cs
Normal file
46
ModernKeePassLib/Keys/IUserKey.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2019 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 ModernKeePassLib.Security;
|
||||
|
||||
namespace ModernKeePassLib.Keys
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface to a user key, like a password, key file data, etc.
|
||||
/// </summary>
|
||||
public interface IUserKey
|
||||
{
|
||||
/// <summary>
|
||||
/// Get key data. Querying this property is fast (it returns a
|
||||
/// reference to a cached <c>ProtectedBinary</c> object).
|
||||
/// If no key data is available, <c>null</c> is returned.
|
||||
/// </summary>
|
||||
ProtectedBinary KeyData
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
// /// <summary>
|
||||
// /// Clear the key and securely erase all security-critical information.
|
||||
// /// </summary>
|
||||
// void Clear();
|
||||
}
|
||||
}
|
68
ModernKeePassLib/Keys/KcpCustomKey.cs
Normal file
68
ModernKeePassLib/Keys/KcpCustomKey.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2019 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.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
using ModernKeePassLib.Cryptography;
|
||||
using ModernKeePassLib.Security;
|
||||
|
||||
namespace ModernKeePassLib.Keys
|
||||
{
|
||||
public sealed class KcpCustomKey : IUserKey
|
||||
{
|
||||
private readonly string m_strName;
|
||||
private ProtectedBinary m_pbKey;
|
||||
|
||||
/// <summary>
|
||||
/// Name of the provider that generated the custom key.
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get { return m_strName; }
|
||||
}
|
||||
|
||||
public ProtectedBinary KeyData
|
||||
{
|
||||
get { return m_pbKey; }
|
||||
}
|
||||
|
||||
public KcpCustomKey(string strName, byte[] pbKeyData, bool bPerformHash)
|
||||
{
|
||||
Debug.Assert(strName != null); if(strName == null) throw new ArgumentNullException("strName");
|
||||
Debug.Assert(pbKeyData != null); if(pbKeyData == null) throw new ArgumentNullException("pbKeyData");
|
||||
|
||||
m_strName = strName;
|
||||
|
||||
if(bPerformHash)
|
||||
{
|
||||
byte[] pbRaw = CryptoUtil.HashSha256(pbKeyData);
|
||||
m_pbKey = new ProtectedBinary(true, pbRaw);
|
||||
}
|
||||
else m_pbKey = new ProtectedBinary(true, pbKeyData);
|
||||
}
|
||||
|
||||
// public void Clear()
|
||||
// {
|
||||
// m_pbKey = null;
|
||||
// }
|
||||
}
|
||||
}
|
322
ModernKeePassLib/Keys/KcpKeyFile.cs
Normal file
322
ModernKeePassLib/Keys/KcpKeyFile.cs
Normal file
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2019 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.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
#if ModernKeePassLib
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Windows.Security.Cryptography;
|
||||
using Windows.Security.Cryptography.Core;
|
||||
using Windows.Storage;
|
||||
#else
|
||||
using System.Security.Cryptography;
|
||||
#endif
|
||||
|
||||
using ModernKeePassLib.Cryptography;
|
||||
using ModernKeePassLib.Resources;
|
||||
using ModernKeePassLib.Security;
|
||||
using ModernKeePassLib.Serialization;
|
||||
using ModernKeePassLib.Utility;
|
||||
|
||||
namespace ModernKeePassLib.Keys
|
||||
{
|
||||
/// <summary>
|
||||
/// Key files as provided by the user.
|
||||
/// </summary>
|
||||
public sealed class KcpKeyFile : IUserKey
|
||||
{
|
||||
private string m_strPath;
|
||||
private ProtectedBinary m_pbKeyData;
|
||||
|
||||
/// <summary>
|
||||
/// Path to the key file.
|
||||
/// </summary>
|
||||
public string Path
|
||||
{
|
||||
get { return m_strPath; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get key data. Querying this property is fast (it returns a
|
||||
/// reference to a cached <c>ProtectedBinary</c> object).
|
||||
/// If no key data is available, <c>null</c> is returned.
|
||||
/// </summary>
|
||||
public ProtectedBinary KeyData
|
||||
{
|
||||
get { return m_pbKeyData; }
|
||||
}
|
||||
|
||||
#if ModernKeePassLib
|
||||
public KcpKeyFile(StorageFile strKeyFile)
|
||||
{
|
||||
Construct(IOConnectionInfo.FromFile(strKeyFile), false);
|
||||
}
|
||||
#else
|
||||
public KcpKeyFile(string strKeyFile)
|
||||
{
|
||||
Construct(IOConnectionInfo.FromPath(strKeyFile), false);
|
||||
}
|
||||
|
||||
public KcpKeyFile(string strKeyFile, bool bThrowIfDbFile)
|
||||
{
|
||||
Construct(IOConnectionInfo.FromPath(strKeyFile), bThrowIfDbFile);
|
||||
}
|
||||
#endif
|
||||
|
||||
public KcpKeyFile(IOConnectionInfo iocKeyFile)
|
||||
{
|
||||
Construct(iocKeyFile, false);
|
||||
}
|
||||
|
||||
public KcpKeyFile(IOConnectionInfo iocKeyFile, bool bThrowIfDbFile)
|
||||
{
|
||||
Construct(iocKeyFile, bThrowIfDbFile);
|
||||
}
|
||||
|
||||
private void Construct(IOConnectionInfo iocFile, bool bThrowIfDbFile)
|
||||
{
|
||||
byte[] pbFileData = IOConnection.ReadFile(iocFile);
|
||||
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);
|
||||
if(pbKey == null) pbKey = LoadKeyFile(pbFileData);
|
||||
|
||||
if(pbKey == null) throw new InvalidOperationException();
|
||||
|
||||
m_strPath = iocFile.Path;
|
||||
m_pbKeyData = new ProtectedBinary(true, pbKey);
|
||||
|
||||
MemUtil.ZeroByteArray(pbKey);
|
||||
}
|
||||
|
||||
// public void Clear()
|
||||
// {
|
||||
// m_strPath = string.Empty;
|
||||
// m_pbKeyData = null;
|
||||
// }
|
||||
|
||||
private static byte[] LoadKeyFile(byte[] pbFileData)
|
||||
{
|
||||
if(pbFileData == null) { Debug.Assert(false); return null; }
|
||||
|
||||
int iLength = pbFileData.Length;
|
||||
|
||||
byte[] pbKey = null;
|
||||
if(iLength == 32) pbKey = LoadBinaryKey32(pbFileData);
|
||||
else if(iLength == 64) pbKey = LoadHexKey32(pbFileData);
|
||||
|
||||
if(pbKey == null)
|
||||
pbKey = CryptoUtil.HashSha256(pbFileData);
|
||||
|
||||
return pbKey;
|
||||
}
|
||||
|
||||
private static byte[] LoadBinaryKey32(byte[] pbFileData)
|
||||
{
|
||||
if(pbFileData == null) { Debug.Assert(false); return null; }
|
||||
if(pbFileData.Length != 32) { Debug.Assert(false); return null; }
|
||||
|
||||
return pbFileData;
|
||||
}
|
||||
|
||||
private static byte[] LoadHexKey32(byte[] pbFileData)
|
||||
{
|
||||
if(pbFileData == null) { Debug.Assert(false); return null; }
|
||||
if(pbFileData.Length != 64) { Debug.Assert(false); return null; }
|
||||
|
||||
try
|
||||
{
|
||||
if(!StrUtil.IsHexString(pbFileData, true)) return null;
|
||||
|
||||
string strHex = StrUtil.Utf8.GetString(pbFileData, 0, pbFileData.Length);
|
||||
byte[] pbKey = MemUtil.HexStringToByteArray(strHex);
|
||||
if((pbKey == null) || (pbKey.Length != 32))
|
||||
{
|
||||
Debug.Assert(false);
|
||||
return null;
|
||||
}
|
||||
|
||||
return pbKey;
|
||||
}
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new, random key-file.
|
||||
/// </summary>
|
||||
/// <param name="strFilePath">Path where the key-file should be saved to.
|
||||
/// If the file exists already, it will be overwritten.</param>
|
||||
/// <param name="pbAdditionalEntropy">Additional entropy used to generate
|
||||
/// the random key. May be <c>null</c> (in this case only the KeePass-internal
|
||||
/// random number generator is used).</param>
|
||||
/// <returns>Returns a <c>FileSaveResult</c> error code.</returns>
|
||||
#if ModernKeePassLib
|
||||
public static void Create(StorageFile strFilePath, byte[] pbAdditionalEntropy)
|
||||
#else
|
||||
public static void Create(string strFilePath, byte[] pbAdditionalEntropy)
|
||||
#endif
|
||||
{
|
||||
byte[] pbKey32 = CryptoRandom.Instance.GetRandomBytes(32);
|
||||
if(pbKey32 == null) throw new SecurityException();
|
||||
|
||||
byte[] pbFinalKey32;
|
||||
if((pbAdditionalEntropy == null) || (pbAdditionalEntropy.Length == 0))
|
||||
pbFinalKey32 = pbKey32;
|
||||
else
|
||||
{
|
||||
using(MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
MemUtil.Write(ms, pbAdditionalEntropy);
|
||||
MemUtil.Write(ms, pbKey32);
|
||||
|
||||
pbFinalKey32 = CryptoUtil.HashSha256(ms.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
CreateXmlKeyFile(strFilePath, pbFinalKey32);
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// XML Key Files
|
||||
// ================================================================
|
||||
|
||||
// Sample XML file:
|
||||
// <?xml version="1.0" encoding="utf-8"?>
|
||||
// <KeyFile>
|
||||
// <Meta>
|
||||
// <Version>1.00</Version>
|
||||
// </Meta>
|
||||
// <Key>
|
||||
// <Data>ySFoKuCcJblw8ie6RkMBdVCnAf4EedSch7ItujK6bmI=</Data>
|
||||
// </Key>
|
||||
// </KeyFile>
|
||||
|
||||
private const string RootElementName = "KeyFile";
|
||||
private const string MetaElementName = "Meta";
|
||||
private const string VersionElementName = "Version";
|
||||
private const string KeyElementName = "Key";
|
||||
private const string KeyDataElementName = "Data";
|
||||
|
||||
private static byte[] LoadXmlKeyFile(byte[] pbFileData)
|
||||
{
|
||||
if(pbFileData == null) { Debug.Assert(false); return null; }
|
||||
|
||||
MemoryStream ms = new MemoryStream(pbFileData, false);
|
||||
byte[] pbKeyData = null;
|
||||
|
||||
try
|
||||
{
|
||||
XmlDocument doc = XmlUtilEx.CreateXmlDocument();
|
||||
doc.Load(ms);
|
||||
|
||||
XmlElement el = doc.DocumentElement;
|
||||
if((el == null) || !el.Name.Equals(RootElementName)) return null;
|
||||
if(el.ChildNodes.Count < 2) return null;
|
||||
|
||||
foreach(XmlNode xmlChild in el.ChildNodes)
|
||||
{
|
||||
if(xmlChild.Name.Equals(MetaElementName)) { } // Ignore Meta
|
||||
else if(xmlChild.Name == KeyElementName)
|
||||
{
|
||||
foreach(XmlNode xmlKeyChild in xmlChild.ChildNodes)
|
||||
{
|
||||
if(xmlKeyChild.Name == KeyDataElementName)
|
||||
{
|
||||
if(pbKeyData == null)
|
||||
pbKeyData = Convert.FromBase64String(xmlKeyChild.InnerText);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception) { pbKeyData = null; }
|
||||
finally { ms.Dispose(); }
|
||||
|
||||
return pbKeyData;
|
||||
}
|
||||
#if ModernKeePassLib
|
||||
private static void CreateXmlKeyFile(StorageFile strFile, byte[] pbKeyData)
|
||||
#else
|
||||
private static void CreateXmlKeyFile(string strFile, byte[] pbKeyData)
|
||||
#endif
|
||||
{
|
||||
Debug.Assert(strFile != null);
|
||||
if(strFile == null) throw new ArgumentNullException("strFile");
|
||||
Debug.Assert(pbKeyData != null);
|
||||
if(pbKeyData == null) throw new ArgumentNullException("pbKeyData");
|
||||
|
||||
#if ModernKeePassLib
|
||||
IOConnectionInfo ioc = IOConnectionInfo.FromFile(strFile);
|
||||
#else
|
||||
IOConnectionInfo ioc = IOConnectionInfo.FromPath(strFile);
|
||||
#endif
|
||||
using(Stream s = IOConnection.OpenWrite(ioc))
|
||||
{
|
||||
using(XmlWriter xw = XmlUtilEx.CreateXmlWriter(s))
|
||||
{
|
||||
xw.WriteStartDocument();
|
||||
xw.WriteStartElement(RootElementName); // <KeyFile>
|
||||
|
||||
xw.WriteStartElement(MetaElementName); // <Meta>
|
||||
xw.WriteStartElement(VersionElementName); // <Version>
|
||||
xw.WriteString("1.00");
|
||||
xw.WriteEndElement(); // </Version>
|
||||
xw.WriteEndElement(); // </Meta>
|
||||
|
||||
xw.WriteStartElement(KeyElementName); // <Key>
|
||||
|
||||
xw.WriteStartElement(KeyDataElementName); // <Data>
|
||||
xw.WriteString(Convert.ToBase64String(pbKeyData));
|
||||
xw.WriteEndElement(); // </Data>
|
||||
|
||||
xw.WriteEndElement(); // </Key>
|
||||
|
||||
xw.WriteEndElement(); // </KeyFile>
|
||||
xw.WriteEndDocument();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
111
ModernKeePassLib/Keys/KcpPassword.cs
Normal file
111
ModernKeePassLib/Keys/KcpPassword.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2019 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.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
using ModernKeePassLib.Security;
|
||||
using ModernKeePassLib.Utility;
|
||||
using ModernKeePassLib.Cryptography;
|
||||
|
||||
namespace ModernKeePassLib.Keys
|
||||
{
|
||||
/// <summary>
|
||||
/// Master password/passphrase as provided by the user.
|
||||
/// </summary>
|
||||
public sealed class KcpPassword : IUserKey
|
||||
{
|
||||
private ProtectedString m_psPassword = null; // Optional
|
||||
private ProtectedBinary m_pbKeyData;
|
||||
|
||||
/// <summary>
|
||||
/// Get the password as protected string. This is <c>null</c>
|
||||
/// unless remembering the password has been turned on.
|
||||
/// </summary>
|
||||
public ProtectedString Password
|
||||
{
|
||||
get { return m_psPassword; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get key data. Querying this property is fast (it returns a
|
||||
/// reference to a cached <c>ProtectedBinary</c> object).
|
||||
/// If no key data is available, <c>null</c> is returned.
|
||||
/// </summary>
|
||||
public ProtectedBinary KeyData
|
||||
{
|
||||
get { return m_pbKeyData; }
|
||||
}
|
||||
|
||||
public KcpPassword(byte[] pbPasswordUtf8)
|
||||
{
|
||||
SetKey(pbPasswordUtf8, true);
|
||||
}
|
||||
|
||||
public KcpPassword(byte[] pbPasswordUtf8, bool bRememberPassword)
|
||||
{
|
||||
SetKey(pbPasswordUtf8, bRememberPassword);
|
||||
}
|
||||
|
||||
public KcpPassword(string strPassword)
|
||||
{
|
||||
byte[] pb = StrUtil.Utf8.GetBytes(strPassword);
|
||||
try { SetKey(pb, true); }
|
||||
finally { MemUtil.ZeroByteArray(pb); }
|
||||
}
|
||||
|
||||
private void SetKey(byte[] pbPasswordUtf8, bool bRememberPassword)
|
||||
{
|
||||
Debug.Assert(pbPasswordUtf8 != null);
|
||||
if(pbPasswordUtf8 == null) throw new ArgumentNullException("pbPasswordUtf8");
|
||||
|
||||
#if (DEBUG && !KeePassLibSD)
|
||||
Debug.Assert(ValidatePassword(pbPasswordUtf8));
|
||||
#endif
|
||||
|
||||
byte[] pbRaw = CryptoUtil.HashSha256(pbPasswordUtf8);
|
||||
try { m_pbKeyData = new ProtectedBinary(true, pbRaw); }
|
||||
finally { MemUtil.ZeroByteArray(pbRaw); }
|
||||
|
||||
if(bRememberPassword)
|
||||
m_psPassword = new ProtectedString(true, pbPasswordUtf8);
|
||||
}
|
||||
|
||||
// public void Clear()
|
||||
// {
|
||||
// m_psPassword = null;
|
||||
// m_pbKeyData = null;
|
||||
// }
|
||||
|
||||
#if (DEBUG && !KeePassLibSD)
|
||||
private static bool ValidatePassword(byte[] pb)
|
||||
{
|
||||
try
|
||||
{
|
||||
string str = StrUtil.Utf8.GetString(pb);
|
||||
return str.IsNormalized(NormalizationForm.FormC);
|
||||
}
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
167
ModernKeePassLib/Keys/KcpUserAccount.cs
Normal file
167
ModernKeePassLib/Keys/KcpUserAccount.cs
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2019 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.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Security;
|
||||
|
||||
#if ModernKeePassLib
|
||||
using Windows.Storage;
|
||||
using System.Security.Cryptography;
|
||||
#endif
|
||||
|
||||
using ModernKeePassLib.Cryptography;
|
||||
using ModernKeePassLib.Native;
|
||||
using ModernKeePassLib.Resources;
|
||||
using ModernKeePassLib.Security;
|
||||
using ModernKeePassLib.Utility;
|
||||
|
||||
namespace ModernKeePassLib.Keys
|
||||
{
|
||||
/// <summary>
|
||||
/// A user key depending on the currently logged on Windows user account.
|
||||
/// </summary>
|
||||
public sealed class KcpUserAccount : IUserKey
|
||||
{
|
||||
private ProtectedBinary m_pbKeyData = null;
|
||||
|
||||
// Constant initialization vector (unique for KeePass)
|
||||
private static readonly byte[] m_pbEntropy = new byte[] {
|
||||
0xDE, 0x13, 0x5B, 0x5F, 0x18, 0xA3, 0x46, 0x70,
|
||||
0xB2, 0x57, 0x24, 0x29, 0x69, 0x88, 0x98, 0xE6
|
||||
};
|
||||
|
||||
private const string UserKeyFileName = "ProtectedUserKey.bin";
|
||||
|
||||
/// <summary>
|
||||
/// Get key data. Querying this property is fast (it returns a
|
||||
/// reference to a cached <c>ProtectedBinary</c> object).
|
||||
/// If no key data is available, <c>null</c> is returned.
|
||||
/// </summary>
|
||||
public ProtectedBinary KeyData
|
||||
{
|
||||
get { return m_pbKeyData; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a user account key.
|
||||
/// </summary>
|
||||
public KcpUserAccount()
|
||||
{
|
||||
if(!CryptoUtil.IsProtectedDataSupported)
|
||||
throw new PlatformNotSupportedException(); // Windows 98/ME
|
||||
|
||||
byte[] pbKey = LoadUserKey(false);
|
||||
if(pbKey == null) pbKey = CreateUserKey();
|
||||
if(pbKey == null) // Should never happen
|
||||
{
|
||||
Debug.Assert(false);
|
||||
throw new SecurityException(KLRes.UserAccountKeyError);
|
||||
}
|
||||
|
||||
m_pbKeyData = new ProtectedBinary(true, pbKey);
|
||||
MemUtil.ZeroByteArray(pbKey);
|
||||
}
|
||||
|
||||
// public void Clear()
|
||||
// {
|
||||
// m_pbKeyData = null;
|
||||
// }
|
||||
|
||||
private static string GetUserKeyFilePath(bool bCreate)
|
||||
{
|
||||
#if ModernKeePassLib
|
||||
string strUserDir = Windows.Storage.ApplicationData.Current.RoamingFolder.Path;
|
||||
#else
|
||||
string strUserDir = Environment.GetFolderPath(
|
||||
Environment.SpecialFolder.ApplicationData);
|
||||
#endif
|
||||
|
||||
strUserDir = UrlUtil.EnsureTerminatingSeparator(strUserDir, false);
|
||||
strUserDir += PwDefs.ShortProductName;
|
||||
|
||||
#if !ModernKeePassLib
|
||||
|
||||
if(bCreate && !Directory.Exists(strUserDir))
|
||||
Directory.CreateDirectory(strUserDir);
|
||||
#endif
|
||||
|
||||
strUserDir = UrlUtil.EnsureTerminatingSeparator(strUserDir, false);
|
||||
return (strUserDir + UserKeyFileName);
|
||||
}
|
||||
|
||||
private static byte[] LoadUserKey(bool bThrow)
|
||||
{
|
||||
byte[] pbKey = null;
|
||||
|
||||
#if !KeePassLibSD
|
||||
try
|
||||
{
|
||||
string strFilePath = GetUserKeyFilePath(false);
|
||||
|
||||
#if ModernKeePassLib
|
||||
var fileStream = StorageFile.GetFileFromPathAsync(strFilePath).GetAwaiter().GetResult().OpenStreamForReadAsync().GetAwaiter().GetResult();
|
||||
var pbProtectedKey = new byte[(int)fileStream.Length];
|
||||
fileStream.Read(pbProtectedKey, 0, (int)fileStream.Length);
|
||||
fileStream.Dispose();
|
||||
#else
|
||||
byte[] pbProtectedKey = File.ReadAllBytes(strFilePath);
|
||||
#endif
|
||||
|
||||
pbKey = CryptoUtil.UnprotectData(pbProtectedKey, m_pbEntropy,
|
||||
DataProtectionScope.CurrentUser);
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
if(bThrow) throw;
|
||||
pbKey = null;
|
||||
}
|
||||
#endif
|
||||
|
||||
return pbKey;
|
||||
}
|
||||
|
||||
private static byte[] CreateUserKey()
|
||||
{
|
||||
#if KeePassLibSD
|
||||
return null;
|
||||
#else
|
||||
string strFilePath = GetUserKeyFilePath(true);
|
||||
|
||||
byte[] pbRandomKey = CryptoRandom.Instance.GetRandomBytes(64);
|
||||
byte[] pbProtectedKey = CryptoUtil.ProtectData(pbRandomKey,
|
||||
m_pbEntropy, DataProtectionScope.CurrentUser);
|
||||
#if ModernKeePassLib
|
||||
var fileStream = StorageFile.GetFileFromPathAsync(strFilePath).GetAwaiter().GetResult().OpenStreamForWriteAsync().GetAwaiter().GetResult();
|
||||
fileStream.Write(pbProtectedKey, 0, (int)fileStream.Length);
|
||||
fileStream.Dispose();
|
||||
#else
|
||||
File.WriteAllBytes(strFilePath, pbProtectedKey);
|
||||
#endif
|
||||
|
||||
byte[] pbKey = LoadUserKey(true);
|
||||
Debug.Assert(MemUtil.ArraysEqual(pbKey, pbRandomKey));
|
||||
|
||||
MemUtil.ZeroByteArray(pbRandomKey);
|
||||
return pbKey;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
152
ModernKeePassLib/Keys/KeyProvider.cs
Normal file
152
ModernKeePassLib/Keys/KeyProvider.cs
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2019 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 ModernKeePassLib.Serialization;
|
||||
|
||||
namespace ModernKeePassLib.Keys
|
||||
{
|
||||
public sealed class KeyProviderQueryContext
|
||||
{
|
||||
private IOConnectionInfo m_ioInfo;
|
||||
public IOConnectionInfo DatabaseIOInfo
|
||||
{
|
||||
get { return m_ioInfo; }
|
||||
}
|
||||
|
||||
public string DatabasePath
|
||||
{
|
||||
get { return m_ioInfo.Path; }
|
||||
}
|
||||
|
||||
private bool m_bCreatingNewKey;
|
||||
public bool CreatingNewKey
|
||||
{
|
||||
get { return m_bCreatingNewKey; }
|
||||
}
|
||||
|
||||
private bool m_bSecDesktop;
|
||||
public bool IsOnSecureDesktop
|
||||
{
|
||||
get { return m_bSecDesktop; }
|
||||
}
|
||||
|
||||
public KeyProviderQueryContext(IOConnectionInfo ioInfo, bool bCreatingNewKey,
|
||||
bool bOnSecDesktop)
|
||||
{
|
||||
if(ioInfo == null) throw new ArgumentNullException("ioInfo");
|
||||
|
||||
m_ioInfo = ioInfo.CloneDeep();
|
||||
m_bCreatingNewKey = bCreatingNewKey;
|
||||
m_bSecDesktop = bOnSecDesktop;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class KeyProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of your key provider (should be unique).
|
||||
/// </summary>
|
||||
public abstract string Name
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Property indicating whether the provider is exclusive.
|
||||
/// If the provider is exclusive, KeePass doesn't allow other
|
||||
/// key sources (master password, Windows user account, ...)
|
||||
/// to be combined with the provider.
|
||||
/// Key providers typically should return <c>false</c>
|
||||
/// (to allow non-exclusive use), i.e. don't override this
|
||||
/// property.
|
||||
/// </summary>
|
||||
public virtual bool Exclusive
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Property that specifies whether the returned key data
|
||||
/// gets hashed by KeePass first or is written directly to
|
||||
/// the user key data stream.
|
||||
/// Standard key provider plugins should return <c>false</c>
|
||||
/// (i.e. don't overwrite this property). Returning <c>true</c>
|
||||
/// may cause severe security problems and is highly
|
||||
/// discouraged.
|
||||
/// </summary>
|
||||
public virtual bool DirectKey
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
// public virtual PwIcon ImageIndex
|
||||
// {
|
||||
// get { return PwIcon.UserKey; }
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// This property specifies whether the <c>GetKey</c> method might
|
||||
/// show a form or dialog. If there is any chance that the method shows
|
||||
/// one, this property must return <c>true</c>. Only if it's guaranteed
|
||||
/// that the <c>GetKey</c> method doesn't show any form or dialog, this
|
||||
/// property should return <c>false</c>.
|
||||
/// </summary>
|
||||
public virtual bool GetKeyMightShowGui
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This property specifies whether the key provider is compatible
|
||||
/// with the secure desktop mode. This almost never is the case,
|
||||
/// so you usually won't override this property.
|
||||
/// </summary>
|
||||
public virtual bool SecureDesktopCompatible
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public abstract byte[] GetKey(KeyProviderQueryContext ctx);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
public sealed class SampleKeyProvider : KeyProvider
|
||||
{
|
||||
public override string Name
|
||||
{
|
||||
get { return "Built-In Sample Key Provider"; }
|
||||
}
|
||||
|
||||
// Do not just copy this to your own key provider class! See above.
|
||||
public override bool GetKeyMightShowGui
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public override byte[] GetKey(KeyProviderQueryContext ctx)
|
||||
{
|
||||
return new byte[]{ 2, 3, 5, 7, 11, 13 };
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
105
ModernKeePassLib/Keys/KeyProviderPool.cs
Normal file
105
ModernKeePassLib/Keys/KeyProviderPool.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2019 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ModernKeePassLib.Keys
|
||||
{
|
||||
public sealed class KeyProviderPool : IEnumerable<KeyProvider>
|
||||
{
|
||||
private List<KeyProvider> m_vProviders = new List<KeyProvider>();
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return m_vProviders.Count; }
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return m_vProviders.GetEnumerator();
|
||||
}
|
||||
|
||||
public IEnumerator<KeyProvider> GetEnumerator()
|
||||
{
|
||||
return m_vProviders.GetEnumerator();
|
||||
}
|
||||
|
||||
public void Add(KeyProvider prov)
|
||||
{
|
||||
Debug.Assert(prov != null); if(prov == null) throw new ArgumentNullException("prov");
|
||||
|
||||
m_vProviders.Add(prov);
|
||||
}
|
||||
|
||||
public bool Remove(KeyProvider prov)
|
||||
{
|
||||
Debug.Assert(prov != null); if(prov == null) throw new ArgumentNullException("prov");
|
||||
|
||||
return m_vProviders.Remove(prov);
|
||||
}
|
||||
|
||||
public KeyProvider Get(string strProviderName)
|
||||
{
|
||||
if(strProviderName == null) throw new ArgumentNullException("strProviderName");
|
||||
|
||||
foreach(KeyProvider prov in m_vProviders)
|
||||
{
|
||||
if(prov.Name == strProviderName) return prov;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsKeyProvider(string strName)
|
||||
{
|
||||
Debug.Assert(strName != null); if(strName == null) throw new ArgumentNullException("strName");
|
||||
|
||||
foreach(KeyProvider prov in m_vProviders)
|
||||
{
|
||||
if(prov.Name == strName) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal byte[] GetKey(string strProviderName, KeyProviderQueryContext ctx,
|
||||
out bool bPerformHash)
|
||||
{
|
||||
Debug.Assert(strProviderName != null); if(strProviderName == null) throw new ArgumentNullException("strProviderName");
|
||||
|
||||
bPerformHash = true;
|
||||
|
||||
foreach(KeyProvider prov in m_vProviders)
|
||||
{
|
||||
if(prov.Name == strProviderName)
|
||||
{
|
||||
bPerformHash = !prov.DirectKey;
|
||||
return prov.GetKey(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Assert(false);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
51
ModernKeePassLib/Keys/KeyValidator.cs
Normal file
51
ModernKeePassLib/Keys/KeyValidator.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2019 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;
|
||||
|
||||
namespace ModernKeePassLib.Keys
|
||||
{
|
||||
public enum KeyValidationType
|
||||
{
|
||||
MasterPassword = 0
|
||||
}
|
||||
|
||||
public abstract class KeyValidator
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of your key validator (should be unique).
|
||||
/// </summary>
|
||||
public abstract string Name
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate a key.
|
||||
/// </summary>
|
||||
/// <param name="strKey">Key to validate.</param>
|
||||
/// <param name="t">Type of the validation to perform.</param>
|
||||
/// <returns>Returns <c>null</c>, if the validation is successful.
|
||||
/// If there's a problem with the key, the returned string describes
|
||||
/// the problem.</returns>
|
||||
public abstract string Validate(string strKey, KeyValidationType t);
|
||||
}
|
||||
}
|
86
ModernKeePassLib/Keys/KeyValidatorPool.cs
Normal file
86
ModernKeePassLib/Keys/KeyValidatorPool.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2019 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
|
||||
using ModernKeePassLib.Utility;
|
||||
|
||||
namespace ModernKeePassLib.Keys
|
||||
{
|
||||
public sealed class KeyValidatorPool : IEnumerable<KeyValidator>
|
||||
{
|
||||
private List<KeyValidator> m_vValidators = new List<KeyValidator>();
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return m_vValidators.Count; }
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return m_vValidators.GetEnumerator();
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValidator> GetEnumerator()
|
||||
{
|
||||
return m_vValidators.GetEnumerator();
|
||||
}
|
||||
|
||||
public void Add(KeyValidator v)
|
||||
{
|
||||
Debug.Assert(v != null); if(v == null) throw new ArgumentNullException("v");
|
||||
|
||||
m_vValidators.Add(v);
|
||||
}
|
||||
|
||||
public bool Remove(KeyValidator v)
|
||||
{
|
||||
Debug.Assert(v != null); if(v == null) throw new ArgumentNullException("v");
|
||||
|
||||
return m_vValidators.Remove(v);
|
||||
}
|
||||
|
||||
public string Validate(string strKey, KeyValidationType t)
|
||||
{
|
||||
Debug.Assert(strKey != null); if(strKey == null) throw new ArgumentNullException("strKey");
|
||||
|
||||
foreach(KeyValidator v in m_vValidators)
|
||||
{
|
||||
string strResult = v.Validate(strKey, t);
|
||||
if(strResult != null) return strResult;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public string Validate(byte[] pbKeyUtf8, KeyValidationType t)
|
||||
{
|
||||
Debug.Assert(pbKeyUtf8 != null); if(pbKeyUtf8 == null) throw new ArgumentNullException("pbKeyUtf8");
|
||||
|
||||
if(m_vValidators.Count == 0) return null;
|
||||
|
||||
string strKey = StrUtil.Utf8.GetString(pbKeyUtf8, 0, pbKeyUtf8.Length);
|
||||
return Validate(strKey, t);
|
||||
}
|
||||
}
|
||||
}
|
33
ModernKeePassLib/Keys/UserKeyType.cs
Normal file
33
ModernKeePassLib/Keys/UserKeyType.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2019 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;
|
||||
|
||||
namespace ModernKeePassLib.Keys
|
||||
{
|
||||
[Flags]
|
||||
public enum UserKeyType
|
||||
{
|
||||
None = 0,
|
||||
Other = 1,
|
||||
Password = 2,
|
||||
KeyFile = 4,
|
||||
UserAccount = 8
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user