Merge branch 'Keepass_Orig'
Conflicts: src/KeePassLib2Android/Cryptography/CryptoRandom.cs src/KeePassLib2Android/Cryptography/HashingStreamEx.cs src/KeePassLib2Android/Cryptography/HmacOtp.cs src/KeePassLib2Android/Cryptography/PasswordGenerator/CharSetBasedGenerator.cs src/KeePassLib2Android/Cryptography/PasswordGenerator/CustomPwGenerator.cs src/KeePassLib2Android/Cryptography/PasswordGenerator/CustomPwGeneratorPool.cs src/KeePassLib2Android/Cryptography/PasswordGenerator/PatternBasedGenerator.cs src/KeePassLib2Android/Cryptography/PasswordGenerator/PwCharSet.cs src/KeePassLib2Android/Cryptography/PasswordGenerator/PwGenerator.cs src/KeePassLib2Android/Cryptography/PasswordGenerator/PwProfile.cs src/KeePassLib2Android/Cryptography/PopularPasswords.cs src/KeePassLib2Android/Cryptography/QualityEstimation.cs src/KeePassLib2Android/Cryptography/SelfTest.cs src/KeePassLib2Android/Delegates/Handlers.cs src/KeePassLib2Android/Interfaces/IDeepCloneable.cs src/KeePassLib2Android/Interfaces/IStatusLogger.cs src/KeePassLib2Android/Interfaces/IStructureItem.cs src/KeePassLib2Android/Interfaces/ITimeLogger.cs src/KeePassLib2Android/Interfaces/IUIOperations.cs src/KeePassLib2Android/Interfaces/IXmlSerializerEx.cs src/KeePassLib2Android/Keys/IUserKey.cs src/KeePassLib2Android/Keys/KcpCustomKey.cs src/KeePassLib2Android/Keys/KcpUserAccount.cs src/KeePassLib2Android/PwCustomIcon.cs src/KeePassLib2Android/PwGroup.cs src/KeePassLib2Android/Serialization/FileTransactionEx.cs src/KeePassLib2Android/Serialization/HashedBlockStream.cs src/KeePassLib2Android/Serialization/IOConnection.cs src/KeePassLib2Android/Serialization/KdbxFile.Read.cs src/KeePassLib2Android/Serialization/KdbxFile.Write.cs src/KeePassLib2Android/Translation/KPControlCustomization.cs src/KeePassLib2Android/Translation/KPFormCustomization.cs src/KeePassLib2Android/Utility/GfxUtil.cs src/KeePassLib2Android/Utility/MessageService.cs src/KeePassLib2Android/Utility/MonoWorkarounds.cs src/KeePassLib2Android/Utility/TimeUtil.cs
This commit is contained in:
		@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										174
									
								
								src/KeePassLib2Android/Collections/ProtectedBinarySet.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								src/KeePassLib2Android/Collections/ProtectedBinarySet.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,174 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2017 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.Diagnostics;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using KeePassLib.Delegates;
 | 
			
		||||
using KeePassLib.Security;
 | 
			
		||||
 | 
			
		||||
namespace KeePassLib.Collections
 | 
			
		||||
{
 | 
			
		||||
	internal sealed class ProtectedBinarySet : IEnumerable<KeyValuePair<int, ProtectedBinary>>
 | 
			
		||||
	{
 | 
			
		||||
		private Dictionary<int, ProtectedBinary> m_d =
 | 
			
		||||
			new Dictionary<int, ProtectedBinary>();
 | 
			
		||||
 | 
			
		||||
		public ProtectedBinarySet()
 | 
			
		||||
		{
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		IEnumerator IEnumerable.GetEnumerator()
 | 
			
		||||
		{
 | 
			
		||||
			return m_d.GetEnumerator();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public IEnumerator<KeyValuePair<int, ProtectedBinary>> GetEnumerator()
 | 
			
		||||
		{
 | 
			
		||||
			return m_d.GetEnumerator();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void Clear()
 | 
			
		||||
		{
 | 
			
		||||
			m_d.Clear();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private int GetFreeID()
 | 
			
		||||
		{
 | 
			
		||||
			int i = m_d.Count;
 | 
			
		||||
			while(m_d.ContainsKey(i)) { ++i; }
 | 
			
		||||
			Debug.Assert(i == m_d.Count); // m_d.Count should be free
 | 
			
		||||
			return i;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public ProtectedBinary Get(int iID)
 | 
			
		||||
		{
 | 
			
		||||
			ProtectedBinary pb;
 | 
			
		||||
			if(m_d.TryGetValue(iID, out pb)) return pb;
 | 
			
		||||
 | 
			
		||||
			// Debug.Assert(false); // No assert
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public int Find(ProtectedBinary pb)
 | 
			
		||||
		{
 | 
			
		||||
			if(pb == null) { Debug.Assert(false); return -1; }
 | 
			
		||||
 | 
			
		||||
			// Fast search by reference
 | 
			
		||||
			foreach(KeyValuePair<int, ProtectedBinary> kvp in m_d)
 | 
			
		||||
			{
 | 
			
		||||
				if(object.ReferenceEquals(pb, kvp.Value))
 | 
			
		||||
				{
 | 
			
		||||
					Debug.Assert(pb.Equals(kvp.Value));
 | 
			
		||||
					return kvp.Key;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Slow search by content
 | 
			
		||||
			foreach(KeyValuePair<int, ProtectedBinary> kvp in m_d)
 | 
			
		||||
			{
 | 
			
		||||
				if(pb.Equals(kvp.Value)) return kvp.Key;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Debug.Assert(false); // No assert
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void Set(int iID, ProtectedBinary pb)
 | 
			
		||||
		{
 | 
			
		||||
			if(iID < 0) { Debug.Assert(false); return; }
 | 
			
		||||
			if(pb == null) { Debug.Assert(false); return; }
 | 
			
		||||
 | 
			
		||||
			m_d[iID] = pb;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void Add(ProtectedBinary pb)
 | 
			
		||||
		{
 | 
			
		||||
			if(pb == null) { Debug.Assert(false); return; }
 | 
			
		||||
 | 
			
		||||
			int i = Find(pb);
 | 
			
		||||
			if(i >= 0) return; // Exists already
 | 
			
		||||
 | 
			
		||||
			i = GetFreeID();
 | 
			
		||||
			m_d[i] = pb;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void AddFrom(ProtectedBinaryDictionary d)
 | 
			
		||||
		{
 | 
			
		||||
			if(d == null) { Debug.Assert(false); return; }
 | 
			
		||||
 | 
			
		||||
			foreach(KeyValuePair<string, ProtectedBinary> kvp in d)
 | 
			
		||||
			{
 | 
			
		||||
				Add(kvp.Value);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void AddFrom(PwGroup pg)
 | 
			
		||||
		{
 | 
			
		||||
			if(pg == null) { Debug.Assert(false); return; }
 | 
			
		||||
 | 
			
		||||
			EntryHandler eh = delegate(PwEntry pe)
 | 
			
		||||
			{
 | 
			
		||||
				if(pe == null) { Debug.Assert(false); return true; }
 | 
			
		||||
 | 
			
		||||
				AddFrom(pe.Binaries);
 | 
			
		||||
				foreach(PwEntry peHistory in pe.History)
 | 
			
		||||
				{
 | 
			
		||||
					if(peHistory == null) { Debug.Assert(false); continue; }
 | 
			
		||||
					AddFrom(peHistory.Binaries);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				return true;
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			pg.TraverseTree(TraversalMethod.PreOrder, null, eh);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public ProtectedBinary[] ToArray()
 | 
			
		||||
		{
 | 
			
		||||
			int n = m_d.Count;
 | 
			
		||||
			ProtectedBinary[] v = new ProtectedBinary[n];
 | 
			
		||||
 | 
			
		||||
			foreach(KeyValuePair<int, ProtectedBinary> kvp in m_d)
 | 
			
		||||
			{
 | 
			
		||||
				if((kvp.Key < 0) || (kvp.Key >= n))
 | 
			
		||||
				{
 | 
			
		||||
					Debug.Assert(false);
 | 
			
		||||
					throw new InvalidOperationException();
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				v[kvp.Key] = kvp.Value;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for(int i = 0; i < n; ++i)
 | 
			
		||||
			{
 | 
			
		||||
				if(v[i] == null)
 | 
			
		||||
				{
 | 
			
		||||
					Debug.Assert(false);
 | 
			
		||||
					throw new InvalidOperationException();
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return v;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -20,11 +20,12 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using KeePassLib.Delegates;
 | 
			
		||||
using KeePassLib.Interfaces;
 | 
			
		||||
using KeePassLib.Utility;
 | 
			
		||||
 | 
			
		||||
#if KeePassLibSD
 | 
			
		||||
using KeePassLibSD;
 | 
			
		||||
@@ -182,7 +183,7 @@ namespace KeePassLib.Collections
 | 
			
		||||
			get { return ((m_l.Count > 0) ? m_l[0] : null); }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private DateTime m_dtLocationChanged = DateTime.MinValue;
 | 
			
		||||
		private DateTime m_dtLocationChanged = TimeUtil.SafeMinValueUtc;
 | 
			
		||||
		public DateTime LocationChanged
 | 
			
		||||
		{
 | 
			
		||||
			get { return m_dtLocationChanged; }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -106,9 +106,12 @@ namespace KeePassLib.Cryptography.Cipher
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		protected override void Dispose(bool bDisposing)
 | 
			
		||||
		{
 | 
			
		||||
			if(bDisposing)
 | 
			
		||||
			{
 | 
			
		||||
				MemUtil.ZeroArray<uint>(m_s);
 | 
			
		||||
				MemUtil.ZeroArray<uint>(m_x);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			base.Dispose(bDisposing);
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -115,8 +115,8 @@ namespace KeePassLib.Cryptography.Cipher
 | 
			
		||||
 | 
			
		||||
		protected override void Dispose(bool bDisposing)
 | 
			
		||||
		{
 | 
			
		||||
			if(!bDisposing) return;
 | 
			
		||||
 | 
			
		||||
			if(bDisposing)
 | 
			
		||||
			{
 | 
			
		||||
				if(m_sBase != null)
 | 
			
		||||
				{
 | 
			
		||||
					m_c.Dispose();
 | 
			
		||||
@@ -129,6 +129,9 @@ namespace KeePassLib.Cryptography.Cipher
 | 
			
		||||
				m_pbBuffer = null;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			base.Dispose(bDisposing);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void Flush()
 | 
			
		||||
		{
 | 
			
		||||
			Debug.Assert(m_sBase != null);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -52,10 +52,13 @@ namespace KeePassLib.Cryptography.Cipher
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		protected virtual void Dispose(bool bDisposing)
 | 
			
		||||
		{
 | 
			
		||||
			if(bDisposing)
 | 
			
		||||
			{
 | 
			
		||||
				MemUtil.ZeroByteArray(m_pBlock);
 | 
			
		||||
				m_iBlockPos = m_pBlock.Length;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		protected void InvalidateBlock()
 | 
			
		||||
		{
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -71,9 +71,12 @@ namespace KeePassLib.Cryptography.Cipher
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		protected override void Dispose(bool bDisposing)
 | 
			
		||||
		{
 | 
			
		||||
			if(bDisposing)
 | 
			
		||||
			{
 | 
			
		||||
				MemUtil.ZeroArray<uint>(m_s);
 | 
			
		||||
				MemUtil.ZeroArray<uint>(m_x);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			base.Dispose(bDisposing);
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,10 @@
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Globalization;
 | 
			
		||||
using System.IO;
 | 
			
		||||
 | 
			
		||||
#if !KeePassUAP
 | 
			
		||||
@@ -34,8 +37,8 @@ using KeePassLib.Utility;
 | 
			
		||||
namespace KeePassLib.Cryptography
 | 
			
		||||
{
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Cryptographically strong random number generator. The returned values
 | 
			
		||||
	/// are unpredictable and cannot be reproduced.
 | 
			
		||||
	/// Cryptographically secure pseudo-random number generator.
 | 
			
		||||
	/// The returned values are unpredictable and cannot be reproduced.
 | 
			
		||||
	/// <c>CryptoRandom</c> is a singleton class.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public sealed class CryptoRandom
 | 
			
		||||
@@ -91,12 +94,13 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
 | 
			
		||||
		private CryptoRandom()
 | 
			
		||||
		{
 | 
			
		||||
			Random rWeak = new Random();
 | 
			
		||||
			byte[] pb = new byte[8];
 | 
			
		||||
			rWeak.NextBytes(pb);
 | 
			
		||||
			m_uCounter = MemUtil.BytesToUInt64(pb);
 | 
			
		||||
 | 
			
		||||
			AddEntropy(GetSystemData(rWeak));
 | 
			
		||||
			// byte[] pb = new byte[8];
 | 
			
		||||
			// rWeak.NextBytes(pb);
 | 
			
		||||
			// m_uCounter = MemUtil.BytesToUInt64(pb);
 | 
			
		||||
			m_uCounter = (ulong)DateTime.UtcNow.ToBinary();
 | 
			
		||||
 | 
			
		||||
			AddEntropy(GetSystemData());
 | 
			
		||||
			AddEntropy(GetCspData());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -148,7 +152,7 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
		}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static byte[] GetSystemData(Random rWeak)
 | 
			
		||||
		private static byte[] GetSystemData()
 | 
			
		||||
		{
 | 
			
		||||
			MemoryStream ms = new MemoryStream();
 | 
			
		||||
			byte[] pb;
 | 
			
		||||
@@ -175,32 +179,40 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
			 */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
			pb = MemUtil.Int32ToBytes(rWeak.Next());
 | 
			
		||||
			MemUtil.Write(ms, pb);
 | 
			
		||||
 | 
			
		||||
			pb = MemUtil.UInt32ToBytes((uint)NativeLib.GetPlatformID());
 | 
			
		||||
			MemUtil.Write(ms, pb);
 | 
			
		||||
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
#if KeePassUAP
 | 
			
		||||
				string strOS = EnvironmentExt.OSVersion.VersionString;
 | 
			
		||||
#else
 | 
			
		||||
				string strOS = Environment.OSVersion.VersionString;
 | 
			
		||||
#endif
 | 
			
		||||
				AddStrHash(ms, strOS);
 | 
			
		||||
 | 
			
		||||
				pb = MemUtil.Int32ToBytes(Environment.ProcessorCount);
 | 
			
		||||
				MemUtil.Write(ms, pb);
 | 
			
		||||
 | 
			
		||||
#if KeePassUAP
 | 
			
		||||
				Version v = EnvironmentExt.OSVersion.Version;
 | 
			
		||||
#else
 | 
			
		||||
				Version v = Environment.OSVersion.Version;
 | 
			
		||||
#endif
 | 
			
		||||
				pb = MemUtil.Int32ToBytes(v.GetHashCode());
 | 
			
		||||
				MemUtil.Write(ms, pb);
 | 
			
		||||
 | 
			
		||||
#if !KeePassUAP
 | 
			
		||||
				AddStrHash(ms, Environment.CommandLine);
 | 
			
		||||
 | 
			
		||||
				pb = MemUtil.Int64ToBytes(Environment.WorkingSet);
 | 
			
		||||
				MemUtil.Write(ms, pb);
 | 
			
		||||
#endif
 | 
			
		||||
			}
 | 
			
		||||
			catch(Exception) { Debug.Assert(false); }
 | 
			
		||||
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
				foreach(DictionaryEntry de in Environment.GetEnvironmentVariables())
 | 
			
		||||
				{
 | 
			
		||||
					AddStrHash(ms, (de.Key as string));
 | 
			
		||||
					AddStrHash(ms, (de.Value as string));
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			catch(Exception) { Debug.Assert(false); }
 | 
			
		||||
 | 
			
		||||
#if KeePassUAP
 | 
			
		||||
			pb = DiagnosticsExt.GetProcessEntropy();
 | 
			
		||||
			MemUtil.Write(ms, pb);
 | 
			
		||||
@@ -249,6 +261,18 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
			}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
				CultureInfo ci = CultureInfo.CurrentCulture;
 | 
			
		||||
				if(ci != null)
 | 
			
		||||
				{
 | 
			
		||||
					pb = MemUtil.Int32ToBytes(ci.GetHashCode());
 | 
			
		||||
					MemUtil.Write(ms, pb);
 | 
			
		||||
				}
 | 
			
		||||
				else { Debug.Assert(false); }
 | 
			
		||||
			}
 | 
			
		||||
			catch(Exception) { Debug.Assert(false); }
 | 
			
		||||
 | 
			
		||||
			pb = Guid.NewGuid().ToByteArray();
 | 
			
		||||
			MemUtil.Write(ms, pb);
 | 
			
		||||
 | 
			
		||||
@@ -257,6 +281,16 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
			return pbAll;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static void AddStrHash(Stream s, string str)
 | 
			
		||||
		{
 | 
			
		||||
			if(s == null) { Debug.Assert(false); return; }
 | 
			
		||||
			if(string.IsNullOrEmpty(str)) return;
 | 
			
		||||
 | 
			
		||||
			byte[] pbUtf8 = StrUtil.Utf8.GetBytes(str);
 | 
			
		||||
			byte[] pbHash = CryptoUtil.HashSha256(pbUtf8);
 | 
			
		||||
			MemUtil.Write(s, pbHash);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private byte[] GetCspData()
 | 
			
		||||
		{
 | 
			
		||||
			byte[] pbCspRandom = new byte[32];
 | 
			
		||||
@@ -321,7 +355,7 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
				byte[] pbRandom256 = GenerateRandom256();
 | 
			
		||||
				Debug.Assert(pbRandom256.Length == 32);
 | 
			
		||||
 | 
			
		||||
				int cbCopy = Math.Min(cbRem, 32);
 | 
			
		||||
				int cbCopy = Math.Min(cbRem, pbRandom256.Length);
 | 
			
		||||
				Array.Copy(pbRandom256, 0, pbRes, iPos, cbCopy);
 | 
			
		||||
 | 
			
		||||
				MemUtil.ZeroByteArray(pbRandom256);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -64,7 +64,7 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
	/// properties, but for the same seed always the same stream
 | 
			
		||||
	/// is produced, i.e. this class can be used as stream cipher.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public sealed class CryptoRandomStream
 | 
			
		||||
	public sealed class CryptoRandomStream : IDisposable
 | 
			
		||||
	{
 | 
			
		||||
		private readonly CrsAlgorithm m_crsAlgorithm;
 | 
			
		||||
 | 
			
		||||
@@ -149,6 +149,30 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void Dispose()
 | 
			
		||||
		{
 | 
			
		||||
			Dispose(true);
 | 
			
		||||
			GC.SuppressFinalize(this);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void Dispose(bool disposing)
 | 
			
		||||
		{
 | 
			
		||||
			if(disposing)
 | 
			
		||||
			{
 | 
			
		||||
				if(m_crsAlgorithm == CrsAlgorithm.ChaCha20)
 | 
			
		||||
					m_chacha20.Dispose();
 | 
			
		||||
				else if(m_crsAlgorithm == CrsAlgorithm.Salsa20)
 | 
			
		||||
					m_salsa20.Dispose();
 | 
			
		||||
				else if(m_crsAlgorithm == CrsAlgorithm.ArcFourVariant)
 | 
			
		||||
				{
 | 
			
		||||
					MemUtil.ZeroByteArray(m_pbState);
 | 
			
		||||
					m_i = 0;
 | 
			
		||||
					m_j = 0;
 | 
			
		||||
				}
 | 
			
		||||
				else { Debug.Assert(false); }
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Get <paramref name="uRequestedCount" /> random bytes.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
@@ -220,9 +244,11 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
			int nStart = Environment.TickCount;
 | 
			
		||||
			for(int i = 0; i < nRounds; ++i)
 | 
			
		||||
			{
 | 
			
		||||
				CryptoRandomStream c = new CryptoRandomStream(cra, pbKey);
 | 
			
		||||
				using(CryptoRandomStream c = new CryptoRandomStream(cra, pbKey))
 | 
			
		||||
				{
 | 
			
		||||
					c.GetRandomBytes((uint)nDataSize);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			int nEnd = Environment.TickCount;
 | 
			
		||||
 | 
			
		||||
			return (nEnd - nStart);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -20,9 +20,12 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Security.Cryptography;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
#if !KeePassUAP
 | 
			
		||||
using System.Security.Cryptography;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
using KeePassLib.Utility;
 | 
			
		||||
 | 
			
		||||
namespace KeePassLib.Cryptography
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -23,9 +23,12 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Security.Cryptography;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
#if !KeePassUAP
 | 
			
		||||
using System.Security.Cryptography;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
using KeePassLib.Utility;
 | 
			
		||||
 | 
			
		||||
namespace KeePassLib.Cryptography.Hash
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -30,7 +30,7 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
{
 | 
			
		||||
	public sealed class HashingStreamEx : Stream
 | 
			
		||||
	{
 | 
			
		||||
		private Stream m_sBaseStream;
 | 
			
		||||
		private readonly Stream m_sBaseStream;
 | 
			
		||||
		private bool m_bWriting;
 | 
			
		||||
		private HashAlgorithm m_hash;
 | 
			
		||||
 | 
			
		||||
@@ -105,11 +105,8 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
#if KeePassRT
 | 
			
		||||
		protected override void Dispose(bool disposing)
 | 
			
		||||
		{
 | 
			
		||||
			if(!disposing) return;
 | 
			
		||||
#else
 | 
			
		||||
		public override void Close()
 | 
			
		||||
			if(disposing)
 | 
			
		||||
		{
 | 
			
		||||
#endif
 | 
			
		||||
			if(m_hash != null)
 | 
			
		||||
			{
 | 
			
		||||
				try
 | 
			
		||||
@@ -126,6 +123,14 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
			m_sBaseStream.Close();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
			base.Dispose(disposing);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void Flush()
 | 
			
		||||
		{
 | 
			
		||||
			m_sBaseStream.Flush();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override long Seek(long lOffset, SeekOrigin soOrigin)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotSupportedException();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -77,6 +77,16 @@ namespace KeePassLib.Cryptography.KeyDerivation
 | 
			
		||||
			public ulong Lane = 0;
 | 
			
		||||
			public ulong Slice = 0;
 | 
			
		||||
			public ulong Index = 0;
 | 
			
		||||
 | 
			
		||||
			public void Release()
 | 
			
		||||
			{
 | 
			
		||||
				if(this.Finished != null)
 | 
			
		||||
				{
 | 
			
		||||
					this.Finished.Close();
 | 
			
		||||
					this.Finished = null;
 | 
			
		||||
				}
 | 
			
		||||
				else { Debug.Assert(false); }
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static byte[] Argon2d(byte[] pbMsg, byte[] pbSalt, uint uParallel,
 | 
			
		||||
@@ -104,7 +114,12 @@ namespace KeePassLib.Cryptography.KeyDerivation
 | 
			
		||||
			ctx.LaneLength = ctx.SegmentLength * NbSyncPoints;
 | 
			
		||||
 | 
			
		||||
			Debug.Assert(NbBlockSize == (NbBlockSizeInQW *
 | 
			
		||||
				(ulong)Marshal.SizeOf(typeof(ulong))));
 | 
			
		||||
#if KeePassUAP
 | 
			
		||||
				(ulong)Marshal.SizeOf<ulong>()
 | 
			
		||||
#else
 | 
			
		||||
				(ulong)Marshal.SizeOf(typeof(ulong))
 | 
			
		||||
#endif
 | 
			
		||||
				));
 | 
			
		||||
			ctx.Mem = new ulong[ctx.MemoryBlocks * NbBlockSizeInQW];
 | 
			
		||||
 | 
			
		||||
			Blake2b h = new Blake2b();
 | 
			
		||||
@@ -186,8 +201,13 @@ namespace KeePassLib.Cryptography.KeyDerivation
 | 
			
		||||
			// for(int i = 0; i < (int)NbBlockSizeInQW; ++i)
 | 
			
		||||
			//	vDst[iDstOffset + i] = vSrc[iSrcOffset + i];
 | 
			
		||||
 | 
			
		||||
#if KeePassUAP
 | 
			
		||||
			Array.Copy(vSrc, (int)uSrcOffset, vDst, (int)uDstOffset,
 | 
			
		||||
				(int)NbBlockSizeInQW);
 | 
			
		||||
#else
 | 
			
		||||
			Array.Copy(vSrc, (long)uSrcOffset, vDst, (long)uDstOffset,
 | 
			
		||||
				(long)NbBlockSizeInQW);
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static void XorBlock(ulong[] vDst, ulong uDstOffset, ulong[] vSrc,
 | 
			
		||||
@@ -456,7 +476,10 @@ namespace KeePassLib.Cryptography.KeyDerivation
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					for(int l = 0; l < np; ++l)
 | 
			
		||||
					{
 | 
			
		||||
						v[l].Finished.WaitOne();
 | 
			
		||||
						v[l].Release();
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -47,7 +47,7 @@ namespace KeePassLib.Cryptography.PasswordGenerator
 | 
			
		||||
 | 
			
		||||
				if(ch == char.MinValue)
 | 
			
		||||
				{
 | 
			
		||||
					Array.Clear(vGenerated, 0, vGenerated.Length);
 | 
			
		||||
					MemUtil.ZeroArray<char>(vGenerated);
 | 
			
		||||
					return PwgError.TooFewCharacters;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
@@ -57,7 +57,7 @@ namespace KeePassLib.Cryptography.PasswordGenerator
 | 
			
		||||
			byte[] pbUtf8 = StrUtil.Utf8.GetBytes(vGenerated);
 | 
			
		||||
			psOut = new ProtectedString(true, pbUtf8);
 | 
			
		||||
			MemUtil.ZeroByteArray(pbUtf8);
 | 
			
		||||
			Array.Clear(vGenerated, 0, vGenerated.Length);
 | 
			
		||||
			MemUtil.ZeroArray<char>(vGenerated);
 | 
			
		||||
 | 
			
		||||
			return PwgError.Success;
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -121,7 +121,7 @@ namespace KeePassLib.Cryptography.PasswordGenerator
 | 
			
		||||
			byte[] pbUtf8 = StrUtil.Utf8.GetBytes(vArray);
 | 
			
		||||
			psOut = new ProtectedString(true, pbUtf8);
 | 
			
		||||
			MemUtil.ZeroByteArray(pbUtf8);
 | 
			
		||||
			Array.Clear(vArray, 0, vArray.Length);
 | 
			
		||||
			MemUtil.ZeroArray<char>(vArray);
 | 
			
		||||
			vGenerated.Clear();
 | 
			
		||||
 | 
			
		||||
			return PwgError.Success;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -46,6 +46,8 @@ namespace KeePassLib.Cryptography.PasswordGenerator
 | 
			
		||||
		public const string Invalid = "\t\r\n";
 | 
			
		||||
		public const string LookAlike = @"O0l1I|";
 | 
			
		||||
 | 
			
		||||
		internal const string MenuAccels = PwCharSet.LowerCase + PwCharSet.Digits;
 | 
			
		||||
 | 
			
		||||
		private const int CharTabSize = (0x10000 / 8);
 | 
			
		||||
 | 
			
		||||
		private List<char> m_vChars = new List<char>();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -22,6 +22,10 @@ using System.Collections.Generic;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
 | 
			
		||||
#if !KeePassUAP
 | 
			
		||||
using System.Security.Cryptography;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
using KeePassLib.Security;
 | 
			
		||||
 | 
			
		||||
namespace KeePassLib.Cryptography.PasswordGenerator
 | 
			
		||||
@@ -46,8 +50,12 @@ namespace KeePassLib.Cryptography.PasswordGenerator
 | 
			
		||||
			Debug.Assert(pwProfile != null);
 | 
			
		||||
			if(pwProfile == null) throw new ArgumentNullException("pwProfile");
 | 
			
		||||
 | 
			
		||||
			CryptoRandomStream crs = CreateCryptoStream(pbUserEntropy);
 | 
			
		||||
			PwgError e = PwgError.Unknown;
 | 
			
		||||
			CryptoRandomStream crs = null;
 | 
			
		||||
			byte[] pbKey = null;
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
				crs = CreateRandomStream(pbUserEntropy, out pbKey);
 | 
			
		||||
 | 
			
		||||
			if(pwProfile.GeneratorType == PasswordGeneratorType.CharSet)
 | 
			
		||||
				e = CharSetBasedGenerator.Generate(out psOut, pwProfile, crs);
 | 
			
		||||
@@ -56,13 +64,20 @@ namespace KeePassLib.Cryptography.PasswordGenerator
 | 
			
		||||
			else if(pwProfile.GeneratorType == PasswordGeneratorType.Custom)
 | 
			
		||||
				e = GenerateCustom(out psOut, pwProfile, crs, pwAlgorithmPool);
 | 
			
		||||
			else { Debug.Assert(false); psOut = ProtectedString.Empty; }
 | 
			
		||||
			}
 | 
			
		||||
			finally
 | 
			
		||||
			{
 | 
			
		||||
				if(crs != null) crs.Dispose();
 | 
			
		||||
				if(pbKey != null) MemUtil.ZeroByteArray(pbKey);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return e;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static CryptoRandomStream CreateCryptoStream(byte[] pbAdditionalEntropy)
 | 
			
		||||
		private static CryptoRandomStream CreateRandomStream(byte[] pbAdditionalEntropy,
 | 
			
		||||
			out byte[] pbKey)
 | 
			
		||||
		{
 | 
			
		||||
			byte[] pbKey = CryptoRandom.Instance.GetRandomBytes(256);
 | 
			
		||||
			pbKey = CryptoRandom.Instance.GetRandomBytes(256);
 | 
			
		||||
 | 
			
		||||
			// Mix in additional entropy
 | 
			
		||||
			if((pbAdditionalEntropy != null) && (pbAdditionalEntropy.Length > 0))
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -265,7 +265,7 @@ namespace KeePassLib.Cryptography.PasswordGenerator
 | 
			
		||||
				else pcs.Add(ch);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			Array.Clear(vChars, 0, vChars.Length);
 | 
			
		||||
			MemUtil.ZeroArray<char>(vChars);
 | 
			
		||||
			MemUtil.ZeroByteArray(pbUtf8);
 | 
			
		||||
			return pp;
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -422,7 +422,7 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
 | 
			
		||||
			char[] vChars = StrUtil.Utf8.GetChars(pbUnprotectedUtf8);
 | 
			
		||||
			uint uResult = EstimatePasswordBits(vChars);
 | 
			
		||||
			Array.Clear(vChars, 0, vChars.Length);
 | 
			
		||||
			MemUtil.ZeroArray<char>(vChars);
 | 
			
		||||
 | 
			
		||||
			return uResult;
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -19,34 +19,35 @@
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Security;
 | 
			
		||||
using System.Security.Cryptography;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Globalization;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Globalization;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Security;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
#if KeePassUAP
 | 
			
		||||
using Org.BouncyCastle.Crypto;
 | 
			
		||||
using Org.BouncyCastle.Crypto.Engines;
 | 
			
		||||
using Org.BouncyCastle.Crypto.Parameters;
 | 
			
		||||
#else
 | 
			
		||||
using System.Security.Cryptography;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
using KeePassLib.Cryptography.Cipher;
 | 
			
		||||
using KeePassLib.Cryptography.Hash;
 | 
			
		||||
using KeePassLib.Cryptography.KeyDerivation;
 | 
			
		||||
using KeePassLib.Keys;
 | 
			
		||||
using KeePassLib.Native;
 | 
			
		||||
using KeePassLib.Utility;
 | 
			
		||||
using KeePassLib.Resources;
 | 
			
		||||
using KeePassLib.Security;
 | 
			
		||||
using KeePassLib.Utility;
 | 
			
		||||
 | 
			
		||||
#if (KeePassUAP && KeePassLibSD)
 | 
			
		||||
#error KeePassUAP and KeePassLibSD are mutually exclusive.
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace KeePassLib.Cryptography
 | 
			
		||||
{
 | 
			
		||||
/* #pragma warning disable 1591
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Return values of the <c>SelfTest.Perform</c> method.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	public enum SelfTestResult
 | 
			
		||||
	{
 | 
			
		||||
		Success = 0,
 | 
			
		||||
		RijndaelEcbError = 1,
 | 
			
		||||
		Salsa20Error = 2,
 | 
			
		||||
		NativeKeyTransformationError = 3
 | 
			
		||||
	}
 | 
			
		||||
#pragma warning restore 1591 */
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Class containing self-test methods.
 | 
			
		||||
	/// </summary>
 | 
			
		||||
@@ -61,6 +62,10 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
 | 
			
		||||
			TestRijndael();
 | 
			
		||||
			TestSalsa20();
 | 
			
		||||
			TestChaCha20();
 | 
			
		||||
			TestBlake2b();
 | 
			
		||||
			TestArgon2();
 | 
			
		||||
			TestHmac();
 | 
			
		||||
 | 
			
		||||
			TestNativeKeyTransform();
 | 
			
		||||
			
 | 
			
		||||
@@ -74,28 +79,31 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
			Debug.Assert((int)PwIcon.World == 1);
 | 
			
		||||
			Debug.Assert((int)PwIcon.Warning == 2);
 | 
			
		||||
			Debug.Assert((int)PwIcon.BlackBerry == 68);
 | 
			
		||||
 | 
			
		||||
#if KeePassUAP
 | 
			
		||||
			SelfTestEx.Perform();
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		internal static void TestFipsComplianceProblems()
 | 
			
		||||
		{
 | 
			
		||||
#if !KeePassRT
 | 
			
		||||
			try { new RijndaelManaged(); }
 | 
			
		||||
#if !KeePassUAP
 | 
			
		||||
			try { using(RijndaelManaged r = new RijndaelManaged()) { } }
 | 
			
		||||
			catch(Exception exAes)
 | 
			
		||||
			{
 | 
			
		||||
				throw new SecurityException("AES/Rijndael: " + exAes.Message);
 | 
			
		||||
			}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
			try { new SHA256Managed(); }
 | 
			
		||||
			try { using(SHA256Managed h = new SHA256Managed()) { } }
 | 
			
		||||
			catch(Exception exSha256)
 | 
			
		||||
			{
 | 
			
		||||
				throw new SecurityException("SHA-256: " + exSha256.Message);
 | 
			
		||||
			}
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static void TestRijndael()
 | 
			
		||||
		{
 | 
			
		||||
#if !KeePassRT
 | 
			
		||||
			// Test vector (official ECB test vector #356)
 | 
			
		||||
			byte[] pbIV = new byte[16];
 | 
			
		||||
			byte[] pbTestKey = new byte[32];
 | 
			
		||||
@@ -110,6 +118,13 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
			for(i = 0; i < 16; ++i) pbTestData[i] = 0;
 | 
			
		||||
			pbTestData[0] = 0x04;
 | 
			
		||||
 | 
			
		||||
#if KeePassUAP
 | 
			
		||||
			AesEngine r = new AesEngine();
 | 
			
		||||
			r.Init(true, new KeyParameter(pbTestKey));
 | 
			
		||||
			if(r.GetBlockSize() != pbTestData.Length)
 | 
			
		||||
				throw new SecurityException("AES (BC)");
 | 
			
		||||
			r.ProcessBlock(pbTestData, 0, pbTestData, 0);
 | 
			
		||||
#else
 | 
			
		||||
			RijndaelManaged r = new RijndaelManaged();
 | 
			
		||||
 | 
			
		||||
			if(r.BlockSize != 128) // AES block size
 | 
			
		||||
@@ -125,14 +140,15 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
			ICryptoTransform iCrypt = r.CreateEncryptor();
 | 
			
		||||
 | 
			
		||||
			iCrypt.TransformBlock(pbTestData, 0, 16, pbTestData, 0);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
			if(!MemUtil.ArraysEqual(pbTestData, pbReferenceCT))
 | 
			
		||||
				throw new SecurityException(KLRes.EncAlgorithmAes + ".");
 | 
			
		||||
#endif
 | 
			
		||||
				throw new SecurityException("AES");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static void TestSalsa20()
 | 
			
		||||
		{
 | 
			
		||||
#if DEBUG
 | 
			
		||||
			// Test values from official set 6, vector 3
 | 
			
		||||
			byte[] pbKey = new byte[32] {
 | 
			
		||||
				0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54,
 | 
			
		||||
@@ -149,12 +165,11 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
 | 
			
		||||
			byte[] pb = new byte[16];
 | 
			
		||||
			Salsa20Cipher c = new Salsa20Cipher(pbKey, pbIV);
 | 
			
		||||
			c.Encrypt(pb, pb.Length, false);
 | 
			
		||||
			c.Encrypt(pb, 0, pb.Length);
 | 
			
		||||
			if(!MemUtil.ArraysEqual(pb, pbExpected))
 | 
			
		||||
				throw new SecurityException("Salsa20.");
 | 
			
		||||
				throw new SecurityException("Salsa20-1");
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
			// Extended test in debug mode
 | 
			
		||||
			// Extended test
 | 
			
		||||
			byte[] pbExpected2 = new byte[16] {
 | 
			
		||||
				0xAB, 0xF3, 0x9A, 0x21, 0x0E, 0xEE, 0x89, 0x59,
 | 
			
		||||
				0x8B, 0x71, 0x33, 0x37, 0x70, 0x56, 0xC2, 0xFE
 | 
			
		||||
@@ -166,15 +181,27 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
 | 
			
		||||
			Random r = new Random();
 | 
			
		||||
			int nPos = Salsa20ToPos(c, r, pb.Length, 65536);
 | 
			
		||||
			c.Encrypt(pb, pb.Length, false);
 | 
			
		||||
			Array.Clear(pb, 0, pb.Length);
 | 
			
		||||
			c.Encrypt(pb, 0, pb.Length);
 | 
			
		||||
			if(!MemUtil.ArraysEqual(pb, pbExpected2))
 | 
			
		||||
				throw new SecurityException("Salsa20-2.");
 | 
			
		||||
				throw new SecurityException("Salsa20-2");
 | 
			
		||||
 | 
			
		||||
			nPos = Salsa20ToPos(c, r, nPos + pb.Length, 131008);
 | 
			
		||||
			Array.Clear(pb, 0, pb.Length);
 | 
			
		||||
			c.Encrypt(pb, pb.Length, true);
 | 
			
		||||
			c.Encrypt(pb, 0, pb.Length);
 | 
			
		||||
			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, MemUtil.Int64ToBytes(i));
 | 
			
		||||
				c.Encrypt(z, 0, z.Length);
 | 
			
		||||
				d[MemUtil.ByteArrayToHexString(z)] = true;
 | 
			
		||||
			}
 | 
			
		||||
			if(d.Count != nRounds) throw new SecurityException("Salsa20-4");
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -188,7 +215,7 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
			{
 | 
			
		||||
				int x = r.Next(1, 513);
 | 
			
		||||
				int nGen = Math.Min(nTargetPos - nPos, x);
 | 
			
		||||
				c.Encrypt(pb, nGen, r.Next(0, 2) == 0);
 | 
			
		||||
				c.Encrypt(pb, 0, nGen);
 | 
			
		||||
				nPos += nGen;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@@ -196,6 +223,484 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		private static void TestChaCha20()
 | 
			
		||||
		{
 | 
			
		||||
			// ======================================================
 | 
			
		||||
			// Test vector from RFC 7539, section 2.3.2
 | 
			
		||||
 | 
			
		||||
			byte[] pbKey = new byte[32];
 | 
			
		||||
			for(int i = 0; i < 32; ++i) pbKey[i] = (byte)i;
 | 
			
		||||
 | 
			
		||||
			byte[] pbIV = new byte[12];
 | 
			
		||||
			pbIV[3] = 0x09;
 | 
			
		||||
			pbIV[7] = 0x4A;
 | 
			
		||||
 | 
			
		||||
			byte[] pbExpc = new byte[64] {
 | 
			
		||||
				0x10, 0xF1, 0xE7, 0xE4, 0xD1, 0x3B, 0x59, 0x15,
 | 
			
		||||
				0x50, 0x0F, 0xDD, 0x1F, 0xA3, 0x20, 0x71, 0xC4,
 | 
			
		||||
				0xC7, 0xD1, 0xF4, 0xC7, 0x33, 0xC0, 0x68, 0x03,
 | 
			
		||||
				0x04, 0x22, 0xAA, 0x9A, 0xC3, 0xD4, 0x6C, 0x4E,
 | 
			
		||||
				0xD2, 0x82, 0x64, 0x46, 0x07, 0x9F, 0xAA, 0x09,
 | 
			
		||||
				0x14, 0xC2, 0xD7, 0x05, 0xD9, 0x8B, 0x02, 0xA2,
 | 
			
		||||
				0xB5, 0x12, 0x9C, 0xD1, 0xDE, 0x16, 0x4E, 0xB9,
 | 
			
		||||
				0xCB, 0xD0, 0x83, 0xE8, 0xA2, 0x50, 0x3C, 0x4E
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			byte[] pb = new byte[64];
 | 
			
		||||
 | 
			
		||||
			using(ChaCha20Cipher c = new ChaCha20Cipher(pbKey, pbIV))
 | 
			
		||||
			{
 | 
			
		||||
				c.Seek(64, SeekOrigin.Begin); // Skip first block
 | 
			
		||||
				c.Encrypt(pb, 0, pb.Length);
 | 
			
		||||
 | 
			
		||||
				if(!MemUtil.ArraysEqual(pb, pbExpc))
 | 
			
		||||
					throw new SecurityException("ChaCha20-1");
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
			// ======================================================
 | 
			
		||||
			// Test vector from RFC 7539, section 2.4.2
 | 
			
		||||
 | 
			
		||||
			pbIV[3] = 0;
 | 
			
		||||
 | 
			
		||||
			pb = StrUtil.Utf8.GetBytes("Ladies and Gentlemen of the clas" +
 | 
			
		||||
				@"s of '99: If I could offer you only one tip for " +
 | 
			
		||||
				@"the future, sunscreen would be it.");
 | 
			
		||||
 | 
			
		||||
			pbExpc = new byte[] {
 | 
			
		||||
				0x6E, 0x2E, 0x35, 0x9A, 0x25, 0x68, 0xF9, 0x80,
 | 
			
		||||
				0x41, 0xBA, 0x07, 0x28, 0xDD, 0x0D, 0x69, 0x81,
 | 
			
		||||
				0xE9, 0x7E, 0x7A, 0xEC, 0x1D, 0x43, 0x60, 0xC2,
 | 
			
		||||
				0x0A, 0x27, 0xAF, 0xCC, 0xFD, 0x9F, 0xAE, 0x0B,
 | 
			
		||||
				0xF9, 0x1B, 0x65, 0xC5, 0x52, 0x47, 0x33, 0xAB,
 | 
			
		||||
				0x8F, 0x59, 0x3D, 0xAB, 0xCD, 0x62, 0xB3, 0x57,
 | 
			
		||||
				0x16, 0x39, 0xD6, 0x24, 0xE6, 0x51, 0x52, 0xAB,
 | 
			
		||||
				0x8F, 0x53, 0x0C, 0x35, 0x9F, 0x08, 0x61, 0xD8,
 | 
			
		||||
				0x07, 0xCA, 0x0D, 0xBF, 0x50, 0x0D, 0x6A, 0x61,
 | 
			
		||||
				0x56, 0xA3, 0x8E, 0x08, 0x8A, 0x22, 0xB6, 0x5E,
 | 
			
		||||
				0x52, 0xBC, 0x51, 0x4D, 0x16, 0xCC, 0xF8, 0x06,
 | 
			
		||||
				0x81, 0x8C, 0xE9, 0x1A, 0xB7, 0x79, 0x37, 0x36,
 | 
			
		||||
				0x5A, 0xF9, 0x0B, 0xBF, 0x74, 0xA3, 0x5B, 0xE6,
 | 
			
		||||
				0xB4, 0x0B, 0x8E, 0xED, 0xF2, 0x78, 0x5E, 0x42,
 | 
			
		||||
				0x87, 0x4D
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			byte[] pb64 = new byte[64];
 | 
			
		||||
 | 
			
		||||
			using(ChaCha20Cipher c = new ChaCha20Cipher(pbKey, pbIV))
 | 
			
		||||
			{
 | 
			
		||||
				c.Encrypt(pb64, 0, pb64.Length); // Skip first block
 | 
			
		||||
				c.Encrypt(pb, 0, pb.Length);
 | 
			
		||||
 | 
			
		||||
				if(!MemUtil.ArraysEqual(pb, pbExpc))
 | 
			
		||||
					throw new SecurityException("ChaCha20-2");
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// ======================================================
 | 
			
		||||
			// Test vector from RFC 7539, appendix A.2 #2
 | 
			
		||||
 | 
			
		||||
			Array.Clear(pbKey, 0, pbKey.Length);
 | 
			
		||||
			pbKey[31] = 1;
 | 
			
		||||
 | 
			
		||||
			Array.Clear(pbIV, 0, pbIV.Length);
 | 
			
		||||
			pbIV[11] = 2;
 | 
			
		||||
 | 
			
		||||
			pb = StrUtil.Utf8.GetBytes("Any submission to the IETF inten" +
 | 
			
		||||
				"ded by the Contributor for publication as all or" +
 | 
			
		||||
				" part of an IETF Internet-Draft or RFC and any s" +
 | 
			
		||||
				"tatement made within the context of an IETF acti" +
 | 
			
		||||
				"vity is considered an \"IETF Contribution\". Such " +
 | 
			
		||||
				"statements include oral statements in IETF sessi" +
 | 
			
		||||
				"ons, as well as written and electronic communica" +
 | 
			
		||||
				"tions made at any time or place, which are addressed to");
 | 
			
		||||
 | 
			
		||||
			pbExpc = MemUtil.HexStringToByteArray(
 | 
			
		||||
				"A3FBF07DF3FA2FDE4F376CA23E82737041605D9F4F4F57BD8CFF2C1D4B7955EC" +
 | 
			
		||||
				"2A97948BD3722915C8F3D337F7D370050E9E96D647B7C39F56E031CA5EB6250D" +
 | 
			
		||||
				"4042E02785ECECFA4B4BB5E8EAD0440E20B6E8DB09D881A7C6132F420E527950" +
 | 
			
		||||
				"42BDFA7773D8A9051447B3291CE1411C680465552AA6C405B7764D5E87BEA85A" +
 | 
			
		||||
				"D00F8449ED8F72D0D662AB052691CA66424BC86D2DF80EA41F43ABF937D3259D" +
 | 
			
		||||
				"C4B2D0DFB48A6C9139DDD7F76966E928E635553BA76C5C879D7B35D49EB2E62B" +
 | 
			
		||||
				"0871CDAC638939E25E8A1E0EF9D5280FA8CA328B351C3C765989CBCF3DAA8B6C" +
 | 
			
		||||
				"CC3AAF9F3979C92B3720FC88DC95ED84A1BE059C6499B9FDA236E7E818B04B0B" +
 | 
			
		||||
				"C39C1E876B193BFE5569753F88128CC08AAA9B63D1A16F80EF2554D7189C411F" +
 | 
			
		||||
				"5869CA52C5B83FA36FF216B9C1D30062BEBCFD2DC5BCE0911934FDA79A86F6E6" +
 | 
			
		||||
				"98CED759C3FF9B6477338F3DA4F9CD8514EA9982CCAFB341B2384DD902F3D1AB" +
 | 
			
		||||
				"7AC61DD29C6F21BA5B862F3730E37CFDC4FD806C22F221");
 | 
			
		||||
 | 
			
		||||
			Random r = new Random();
 | 
			
		||||
			using(MemoryStream msEnc = new MemoryStream())
 | 
			
		||||
			{
 | 
			
		||||
				using(ChaCha20Stream c = new ChaCha20Stream(msEnc, true, pbKey, pbIV))
 | 
			
		||||
				{
 | 
			
		||||
					r.NextBytes(pb64);
 | 
			
		||||
					c.Write(pb64, 0, pb64.Length); // Skip first block
 | 
			
		||||
 | 
			
		||||
					int p = 0;
 | 
			
		||||
					while(p < pb.Length)
 | 
			
		||||
					{
 | 
			
		||||
						int cb = r.Next(1, pb.Length - p + 1);
 | 
			
		||||
						c.Write(pb, p, cb);
 | 
			
		||||
						p += cb;
 | 
			
		||||
					}
 | 
			
		||||
					Debug.Assert(p == pb.Length);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				byte[] pbEnc0 = msEnc.ToArray();
 | 
			
		||||
				byte[] pbEnc = MemUtil.Mid(pbEnc0, 64, pbEnc0.Length - 64);
 | 
			
		||||
				if(!MemUtil.ArraysEqual(pbEnc, pbExpc))
 | 
			
		||||
					throw new SecurityException("ChaCha20-3");
 | 
			
		||||
 | 
			
		||||
				using(MemoryStream msCT = new MemoryStream(pbEnc0, false))
 | 
			
		||||
				{
 | 
			
		||||
					using(ChaCha20Stream cDec = new ChaCha20Stream(msCT, false,
 | 
			
		||||
						pbKey, pbIV))
 | 
			
		||||
					{
 | 
			
		||||
						byte[] pbPT = MemUtil.Read(cDec, pbEnc0.Length);
 | 
			
		||||
						if(cDec.ReadByte() >= 0)
 | 
			
		||||
							throw new SecurityException("ChaCha20-4");
 | 
			
		||||
						if(!MemUtil.ArraysEqual(MemUtil.Mid(pbPT, 0, 64), pb64))
 | 
			
		||||
							throw new SecurityException("ChaCha20-5");
 | 
			
		||||
						if(!MemUtil.ArraysEqual(MemUtil.Mid(pbPT, 64, pbEnc.Length), pb))
 | 
			
		||||
							throw new SecurityException("ChaCha20-6");
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// ======================================================
 | 
			
		||||
			// Test vector TC8 from RFC draft by J. Strombergson:
 | 
			
		||||
			// https://tools.ietf.org/html/draft-strombergson-chacha-test-vectors-01
 | 
			
		||||
 | 
			
		||||
			pbKey = new byte[32] {
 | 
			
		||||
				0xC4, 0x6E, 0xC1, 0xB1, 0x8C, 0xE8, 0xA8, 0x78,
 | 
			
		||||
				0x72, 0x5A, 0x37, 0xE7, 0x80, 0xDF, 0xB7, 0x35,
 | 
			
		||||
				0x1F, 0x68, 0xED, 0x2E, 0x19, 0x4C, 0x79, 0xFB,
 | 
			
		||||
				0xC6, 0xAE, 0xBE, 0xE1, 0xA6, 0x67, 0x97, 0x5D
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			// The first 4 bytes are set to zero and a large counter
 | 
			
		||||
			// is used; this makes the RFC 7539 version of ChaCha20
 | 
			
		||||
			// compatible with the original specification by
 | 
			
		||||
			// D. J. Bernstein.
 | 
			
		||||
			pbIV = new byte[12] { 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
				0x1A, 0xDA, 0x31, 0xD5, 0xCF, 0x68, 0x82, 0x21
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			pb = new byte[128];
 | 
			
		||||
 | 
			
		||||
			pbExpc = new byte[128] {
 | 
			
		||||
				0xF6, 0x3A, 0x89, 0xB7, 0x5C, 0x22, 0x71, 0xF9,
 | 
			
		||||
				0x36, 0x88, 0x16, 0x54, 0x2B, 0xA5, 0x2F, 0x06,
 | 
			
		||||
				0xED, 0x49, 0x24, 0x17, 0x92, 0x30, 0x2B, 0x00,
 | 
			
		||||
				0xB5, 0xE8, 0xF8, 0x0A, 0xE9, 0xA4, 0x73, 0xAF,
 | 
			
		||||
				0xC2, 0x5B, 0x21, 0x8F, 0x51, 0x9A, 0xF0, 0xFD,
 | 
			
		||||
				0xD4, 0x06, 0x36, 0x2E, 0x8D, 0x69, 0xDE, 0x7F,
 | 
			
		||||
				0x54, 0xC6, 0x04, 0xA6, 0xE0, 0x0F, 0x35, 0x3F,
 | 
			
		||||
				0x11, 0x0F, 0x77, 0x1B, 0xDC, 0xA8, 0xAB, 0x92,
 | 
			
		||||
 | 
			
		||||
				0xE5, 0xFB, 0xC3, 0x4E, 0x60, 0xA1, 0xD9, 0xA9,
 | 
			
		||||
				0xDB, 0x17, 0x34, 0x5B, 0x0A, 0x40, 0x27, 0x36,
 | 
			
		||||
				0x85, 0x3B, 0xF9, 0x10, 0xB0, 0x60, 0xBD, 0xF1,
 | 
			
		||||
				0xF8, 0x97, 0xB6, 0x29, 0x0F, 0x01, 0xD1, 0x38,
 | 
			
		||||
				0xAE, 0x2C, 0x4C, 0x90, 0x22, 0x5B, 0xA9, 0xEA,
 | 
			
		||||
				0x14, 0xD5, 0x18, 0xF5, 0x59, 0x29, 0xDE, 0xA0,
 | 
			
		||||
				0x98, 0xCA, 0x7A, 0x6C, 0xCF, 0xE6, 0x12, 0x27,
 | 
			
		||||
				0x05, 0x3C, 0x84, 0xE4, 0x9A, 0x4A, 0x33, 0x32
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			using(ChaCha20Cipher c = new ChaCha20Cipher(pbKey, pbIV, true))
 | 
			
		||||
			{
 | 
			
		||||
				c.Decrypt(pb, 0, pb.Length);
 | 
			
		||||
 | 
			
		||||
				if(!MemUtil.ArraysEqual(pb, pbExpc))
 | 
			
		||||
					throw new SecurityException("ChaCha20-7");
 | 
			
		||||
			}
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static void TestBlake2b()
 | 
			
		||||
		{
 | 
			
		||||
#if DEBUG
 | 
			
		||||
			Blake2b h = new Blake2b();
 | 
			
		||||
 | 
			
		||||
			// ======================================================
 | 
			
		||||
			// From https://tools.ietf.org/html/rfc7693
 | 
			
		||||
 | 
			
		||||
			byte[] pbData = StrUtil.Utf8.GetBytes("abc");
 | 
			
		||||
			byte[] pbExpc = new byte[64] {
 | 
			
		||||
				0xBA, 0x80, 0xA5, 0x3F, 0x98, 0x1C, 0x4D, 0x0D,
 | 
			
		||||
				0x6A, 0x27, 0x97, 0xB6, 0x9F, 0x12, 0xF6, 0xE9,
 | 
			
		||||
				0x4C, 0x21, 0x2F, 0x14, 0x68, 0x5A, 0xC4, 0xB7,
 | 
			
		||||
				0x4B, 0x12, 0xBB, 0x6F, 0xDB, 0xFF, 0xA2, 0xD1,
 | 
			
		||||
				0x7D, 0x87, 0xC5, 0x39, 0x2A, 0xAB, 0x79, 0x2D,
 | 
			
		||||
				0xC2, 0x52, 0xD5, 0xDE, 0x45, 0x33, 0xCC, 0x95,
 | 
			
		||||
				0x18, 0xD3, 0x8A, 0xA8, 0xDB, 0xF1, 0x92, 0x5A,
 | 
			
		||||
				0xB9, 0x23, 0x86, 0xED, 0xD4, 0x00, 0x99, 0x23
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			byte[] pbC = h.ComputeHash(pbData);
 | 
			
		||||
			if(!MemUtil.ArraysEqual(pbC, pbExpc))
 | 
			
		||||
				throw new SecurityException("Blake2b-1");
 | 
			
		||||
 | 
			
		||||
			// ======================================================
 | 
			
		||||
			// Computed using the official b2sum tool
 | 
			
		||||
 | 
			
		||||
			pbExpc = new byte[64] {
 | 
			
		||||
				0x78, 0x6A, 0x02, 0xF7, 0x42, 0x01, 0x59, 0x03,
 | 
			
		||||
				0xC6, 0xC6, 0xFD, 0x85, 0x25, 0x52, 0xD2, 0x72,
 | 
			
		||||
				0x91, 0x2F, 0x47, 0x40, 0xE1, 0x58, 0x47, 0x61,
 | 
			
		||||
				0x8A, 0x86, 0xE2, 0x17, 0xF7, 0x1F, 0x54, 0x19,
 | 
			
		||||
				0xD2, 0x5E, 0x10, 0x31, 0xAF, 0xEE, 0x58, 0x53,
 | 
			
		||||
				0x13, 0x89, 0x64, 0x44, 0x93, 0x4E, 0xB0, 0x4B,
 | 
			
		||||
				0x90, 0x3A, 0x68, 0x5B, 0x14, 0x48, 0xB7, 0x55,
 | 
			
		||||
				0xD5, 0x6F, 0x70, 0x1A, 0xFE, 0x9B, 0xE2, 0xCE
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			pbC = h.ComputeHash(MemUtil.EmptyByteArray);
 | 
			
		||||
			if(!MemUtil.ArraysEqual(pbC, pbExpc))
 | 
			
		||||
				throw new SecurityException("Blake2b-2");
 | 
			
		||||
 | 
			
		||||
			// ======================================================
 | 
			
		||||
			// Computed using the official b2sum tool
 | 
			
		||||
 | 
			
		||||
			string strS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.:,;_-\r\n";
 | 
			
		||||
			StringBuilder sb = new StringBuilder();
 | 
			
		||||
			for(int i = 0; i < 1000; ++i) sb.Append(strS);
 | 
			
		||||
			pbData = StrUtil.Utf8.GetBytes(sb.ToString());
 | 
			
		||||
 | 
			
		||||
			pbExpc = new byte[64] {
 | 
			
		||||
				0x59, 0x69, 0x8D, 0x3B, 0x83, 0xF4, 0x02, 0x4E,
 | 
			
		||||
				0xD8, 0x99, 0x26, 0x0E, 0xF4, 0xE5, 0x9F, 0x20,
 | 
			
		||||
				0xDC, 0x31, 0xEE, 0x5B, 0x45, 0xEA, 0xBB, 0xFC,
 | 
			
		||||
				0x1C, 0x0A, 0x8E, 0xED, 0xAA, 0x7A, 0xFF, 0x50,
 | 
			
		||||
				0x82, 0xA5, 0x8F, 0xBC, 0x4A, 0x46, 0xFC, 0xC5,
 | 
			
		||||
				0xEF, 0x44, 0x4E, 0x89, 0x80, 0x7D, 0x3F, 0x1C,
 | 
			
		||||
				0xC1, 0x94, 0x45, 0xBB, 0xC0, 0x2C, 0x95, 0xAA,
 | 
			
		||||
				0x3F, 0x08, 0x8A, 0x93, 0xF8, 0x75, 0x91, 0xB0
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			Random r = new Random();
 | 
			
		||||
			int p = 0;
 | 
			
		||||
			while(p < pbData.Length)
 | 
			
		||||
			{
 | 
			
		||||
				int cb = r.Next(1, pbData.Length - p + 1);
 | 
			
		||||
				h.TransformBlock(pbData, p, cb, pbData, p);
 | 
			
		||||
				p += cb;
 | 
			
		||||
			}
 | 
			
		||||
			Debug.Assert(p == pbData.Length);
 | 
			
		||||
 | 
			
		||||
			h.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0);
 | 
			
		||||
 | 
			
		||||
			if(!MemUtil.ArraysEqual(h.Hash, pbExpc))
 | 
			
		||||
				throw new SecurityException("Blake2b-3");
 | 
			
		||||
 | 
			
		||||
			h.Clear();
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static void TestArgon2()
 | 
			
		||||
		{
 | 
			
		||||
#if DEBUG
 | 
			
		||||
			Argon2Kdf kdf = new Argon2Kdf();
 | 
			
		||||
 | 
			
		||||
			// ======================================================
 | 
			
		||||
			// From the official Argon2 1.3 reference code package
 | 
			
		||||
			// (test vector for Argon2d 1.3); also on
 | 
			
		||||
			// https://tools.ietf.org/html/draft-irtf-cfrg-argon2-00
 | 
			
		||||
 | 
			
		||||
			KdfParameters p = kdf.GetDefaultParameters();
 | 
			
		||||
			kdf.Randomize(p);
 | 
			
		||||
 | 
			
		||||
			Debug.Assert(p.GetUInt32(Argon2Kdf.ParamVersion, 0) == 0x13U);
 | 
			
		||||
 | 
			
		||||
			byte[] pbMsg = new byte[32];
 | 
			
		||||
			for(int i = 0; i < pbMsg.Length; ++i) pbMsg[i] = 1;
 | 
			
		||||
 | 
			
		||||
			p.SetUInt64(Argon2Kdf.ParamMemory, 32 * 1024);
 | 
			
		||||
			p.SetUInt64(Argon2Kdf.ParamIterations, 3);
 | 
			
		||||
			p.SetUInt32(Argon2Kdf.ParamParallelism, 4);
 | 
			
		||||
 | 
			
		||||
			byte[] pbSalt = new byte[16];
 | 
			
		||||
			for(int i = 0; i < pbSalt.Length; ++i) pbSalt[i] = 2;
 | 
			
		||||
			p.SetByteArray(Argon2Kdf.ParamSalt, pbSalt);
 | 
			
		||||
 | 
			
		||||
			byte[] pbKey = new byte[8];
 | 
			
		||||
			for(int i = 0; i < pbKey.Length; ++i) pbKey[i] = 3;
 | 
			
		||||
			p.SetByteArray(Argon2Kdf.ParamSecretKey, pbKey);
 | 
			
		||||
 | 
			
		||||
			byte[] pbAssoc = new byte[12];
 | 
			
		||||
			for(int i = 0; i < pbAssoc.Length; ++i) pbAssoc[i] = 4;
 | 
			
		||||
			p.SetByteArray(Argon2Kdf.ParamAssocData, pbAssoc);
 | 
			
		||||
 | 
			
		||||
			byte[] pbExpc = new byte[32] {
 | 
			
		||||
				0x51, 0x2B, 0x39, 0x1B, 0x6F, 0x11, 0x62, 0x97,
 | 
			
		||||
				0x53, 0x71, 0xD3, 0x09, 0x19, 0x73, 0x42, 0x94,
 | 
			
		||||
				0xF8, 0x68, 0xE3, 0xBE, 0x39, 0x84, 0xF3, 0xC1,
 | 
			
		||||
				0xA1, 0x3A, 0x4D, 0xB9, 0xFA, 0xBE, 0x4A, 0xCB
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			byte[] pb = kdf.Transform(pbMsg, p);
 | 
			
		||||
 | 
			
		||||
			if(!MemUtil.ArraysEqual(pb, pbExpc))
 | 
			
		||||
				throw new SecurityException("Argon2-1");
 | 
			
		||||
 | 
			
		||||
			// ======================================================
 | 
			
		||||
			// From the official Argon2 1.3 reference code package
 | 
			
		||||
			// (test vector for Argon2d 1.0)
 | 
			
		||||
 | 
			
		||||
			p.SetUInt32(Argon2Kdf.ParamVersion, 0x10);
 | 
			
		||||
 | 
			
		||||
			pbExpc = new byte[32] {
 | 
			
		||||
				0x96, 0xA9, 0xD4, 0xE5, 0xA1, 0x73, 0x40, 0x92,
 | 
			
		||||
				0xC8, 0x5E, 0x29, 0xF4, 0x10, 0xA4, 0x59, 0x14,
 | 
			
		||||
				0xA5, 0xDD, 0x1F, 0x5C, 0xBF, 0x08, 0xB2, 0x67,
 | 
			
		||||
				0x0D, 0xA6, 0x8A, 0x02, 0x85, 0xAB, 0xF3, 0x2B
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			pb = kdf.Transform(pbMsg, p);
 | 
			
		||||
 | 
			
		||||
			if(!MemUtil.ArraysEqual(pb, pbExpc))
 | 
			
		||||
				throw new SecurityException("Argon2-2");
 | 
			
		||||
 | 
			
		||||
			// ======================================================
 | 
			
		||||
			// From the official 'phc-winner-argon2-20151206.zip'
 | 
			
		||||
			// (test vector for Argon2d 1.0)
 | 
			
		||||
 | 
			
		||||
			p.SetUInt64(Argon2Kdf.ParamMemory, 16 * 1024);
 | 
			
		||||
 | 
			
		||||
			pbExpc = new byte[32] {
 | 
			
		||||
				0x57, 0xB0, 0x61, 0x3B, 0xFD, 0xD4, 0x13, 0x1A,
 | 
			
		||||
				0x0C, 0x34, 0x88, 0x34, 0xC6, 0x72, 0x9C, 0x2C,
 | 
			
		||||
				0x72, 0x29, 0x92, 0x1E, 0x6B, 0xBA, 0x37, 0x66,
 | 
			
		||||
				0x5D, 0x97, 0x8C, 0x4F, 0xE7, 0x17, 0x5E, 0xD2
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			pb = kdf.Transform(pbMsg, p);
 | 
			
		||||
 | 
			
		||||
			if(!MemUtil.ArraysEqual(pb, pbExpc))
 | 
			
		||||
				throw new SecurityException("Argon2-3");
 | 
			
		||||
 | 
			
		||||
#if SELFTEST_ARGON2_LONG
 | 
			
		||||
			// ======================================================
 | 
			
		||||
			// Computed using the official 'argon2' application
 | 
			
		||||
			// (test vectors for Argon2d 1.3)
 | 
			
		||||
 | 
			
		||||
			p = kdf.GetDefaultParameters();
 | 
			
		||||
 | 
			
		||||
			pbMsg = StrUtil.Utf8.GetBytes("ABC1234");
 | 
			
		||||
 | 
			
		||||
			p.SetUInt64(Argon2Kdf.ParamMemory, (1 << 11) * 1024); // 2 MB
 | 
			
		||||
			p.SetUInt64(Argon2Kdf.ParamIterations, 2);
 | 
			
		||||
			p.SetUInt32(Argon2Kdf.ParamParallelism, 2);
 | 
			
		||||
 | 
			
		||||
			pbSalt = StrUtil.Utf8.GetBytes("somesalt");
 | 
			
		||||
			p.SetByteArray(Argon2Kdf.ParamSalt, pbSalt);
 | 
			
		||||
 | 
			
		||||
			pbExpc = new byte[32] {
 | 
			
		||||
				0x29, 0xCB, 0xD3, 0xA1, 0x93, 0x76, 0xF7, 0xA2,
 | 
			
		||||
				0xFC, 0xDF, 0xB0, 0x68, 0xAC, 0x0B, 0x99, 0xBA,
 | 
			
		||||
				0x40, 0xAC, 0x09, 0x01, 0x73, 0x42, 0xCE, 0xF1,
 | 
			
		||||
				0x29, 0xCC, 0xA1, 0x4F, 0xE1, 0xC1, 0xB7, 0xA3
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			pb = kdf.Transform(pbMsg, p);
 | 
			
		||||
 | 
			
		||||
			if(!MemUtil.ArraysEqual(pb, pbExpc))
 | 
			
		||||
				throw new SecurityException("Argon2-4");
 | 
			
		||||
 | 
			
		||||
			p.SetUInt64(Argon2Kdf.ParamMemory, (1 << 10) * 1024); // 1 MB
 | 
			
		||||
			p.SetUInt64(Argon2Kdf.ParamIterations, 3);
 | 
			
		||||
 | 
			
		||||
			pbExpc = new byte[32] {
 | 
			
		||||
				0x7A, 0xBE, 0x1C, 0x1C, 0x8D, 0x7F, 0xD6, 0xDC,
 | 
			
		||||
				0x7C, 0x94, 0x06, 0x3E, 0xD8, 0xBC, 0xD8, 0x1C,
 | 
			
		||||
				0x2F, 0x87, 0x84, 0x99, 0x12, 0x83, 0xFE, 0x76,
 | 
			
		||||
				0x00, 0x64, 0xC4, 0x58, 0xA4, 0xDA, 0x35, 0x70
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			pb = kdf.Transform(pbMsg, p);
 | 
			
		||||
 | 
			
		||||
			if(!MemUtil.ArraysEqual(pb, pbExpc))
 | 
			
		||||
				throw new SecurityException("Argon2-5");
 | 
			
		||||
 | 
			
		||||
#if SELFTEST_ARGON2_LONGER
 | 
			
		||||
			p.SetUInt64(Argon2Kdf.ParamMemory, (1 << 20) * 1024); // 1 GB
 | 
			
		||||
			p.SetUInt64(Argon2Kdf.ParamIterations, 2);
 | 
			
		||||
			p.SetUInt32(Argon2Kdf.ParamParallelism, 3);
 | 
			
		||||
 | 
			
		||||
			pbExpc = new byte[32] {
 | 
			
		||||
				0xE6, 0xE7, 0xCB, 0xF5, 0x5A, 0x06, 0x93, 0x05,
 | 
			
		||||
				0x32, 0xBA, 0x86, 0xC6, 0x1F, 0x45, 0x17, 0x99,
 | 
			
		||||
				0x65, 0x41, 0x77, 0xF9, 0x30, 0x55, 0x9A, 0xE8,
 | 
			
		||||
				0x3D, 0x21, 0x48, 0xC6, 0x2D, 0x0C, 0x49, 0x11
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			pb = kdf.Transform(pbMsg, p);
 | 
			
		||||
 | 
			
		||||
			if(!MemUtil.ArraysEqual(pb, pbExpc))
 | 
			
		||||
				throw new SecurityException("Argon2-6");
 | 
			
		||||
#endif // SELFTEST_ARGON2_LONGER
 | 
			
		||||
#endif // SELFTEST_ARGON2_LONG
 | 
			
		||||
#endif // DEBUG
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static void TestHmac()
 | 
			
		||||
		{
 | 
			
		||||
#if DEBUG
 | 
			
		||||
			// Test vectors from RFC 4231
 | 
			
		||||
 | 
			
		||||
			byte[] pbKey = new byte[20];
 | 
			
		||||
			for(int i = 0; i < pbKey.Length; ++i) pbKey[i] = 0x0B;
 | 
			
		||||
			byte[] pbMsg = StrUtil.Utf8.GetBytes("Hi There");
 | 
			
		||||
			byte[] pbExpc = new byte[32] {
 | 
			
		||||
				0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53,
 | 
			
		||||
				0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B,
 | 
			
		||||
				0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7,
 | 
			
		||||
				0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7
 | 
			
		||||
			};
 | 
			
		||||
			HmacEval(pbKey, pbMsg, pbExpc, "1");
 | 
			
		||||
 | 
			
		||||
			pbKey = new byte[131];
 | 
			
		||||
			for(int i = 0; i < pbKey.Length; ++i) pbKey[i] = 0xAA;
 | 
			
		||||
			pbMsg = StrUtil.Utf8.GetBytes(
 | 
			
		||||
				"This is a test using a larger than block-size key and " +
 | 
			
		||||
				"a larger than block-size data. The key needs to be " +
 | 
			
		||||
				"hashed before being used by the HMAC algorithm.");
 | 
			
		||||
			pbExpc = new byte[32] {
 | 
			
		||||
				0x9B, 0x09, 0xFF, 0xA7, 0x1B, 0x94, 0x2F, 0xCB,
 | 
			
		||||
				0x27, 0x63, 0x5F, 0xBC, 0xD5, 0xB0, 0xE9, 0x44,
 | 
			
		||||
				0xBF, 0xDC, 0x63, 0x64, 0x4F, 0x07, 0x13, 0x93,
 | 
			
		||||
				0x8A, 0x7F, 0x51, 0x53, 0x5C, 0x3A, 0x35, 0xE2
 | 
			
		||||
			};
 | 
			
		||||
			HmacEval(pbKey, pbMsg, pbExpc, "2");
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
		private static void HmacEval(byte[] pbKey, byte[] pbMsg,
 | 
			
		||||
			byte[] pbExpc, string strID)
 | 
			
		||||
		{
 | 
			
		||||
			using(HMACSHA256 h = new HMACSHA256(pbKey))
 | 
			
		||||
			{
 | 
			
		||||
				h.TransformBlock(pbMsg, 0, pbMsg.Length, pbMsg, 0);
 | 
			
		||||
				h.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0);
 | 
			
		||||
 | 
			
		||||
				byte[] pbHash = h.Hash;
 | 
			
		||||
				if(!MemUtil.ArraysEqual(pbHash, pbExpc))
 | 
			
		||||
					throw new SecurityException("HMAC-SHA-256-" + strID);
 | 
			
		||||
 | 
			
		||||
				// Reuse the object
 | 
			
		||||
				h.Initialize();
 | 
			
		||||
				h.TransformBlock(pbMsg, 0, pbMsg.Length, pbMsg, 0);
 | 
			
		||||
				h.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0);
 | 
			
		||||
 | 
			
		||||
				pbHash = h.Hash;
 | 
			
		||||
				if(!MemUtil.ArraysEqual(pbHash, pbExpc))
 | 
			
		||||
					throw new SecurityException("HMAC-SHA-256-" + strID + "-R");
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		private static void TestNativeKeyTransform()
 | 
			
		||||
		{
 | 
			
		||||
#if DEBUG
 | 
			
		||||
@@ -205,16 +710,16 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
 | 
			
		||||
			byte[] pbManaged = new byte[32];
 | 
			
		||||
			Array.Copy(pbOrgKey, pbManaged, 32);
 | 
			
		||||
			if(CompositeKey.TransformKeyManaged(pbManaged, pbSeed, uRounds) == false)
 | 
			
		||||
				throw new SecurityException("Managed transform.");
 | 
			
		||||
			if(!AesKdf.TransformKeyManaged(pbManaged, pbSeed, uRounds))
 | 
			
		||||
				throw new SecurityException("AES-KDF-1");
 | 
			
		||||
 | 
			
		||||
			byte[] pbNative = new byte[32];
 | 
			
		||||
			Array.Copy(pbOrgKey, pbNative, 32);
 | 
			
		||||
			if(NativeLib.TransformKey256(pbNative, pbSeed, uRounds) == false)
 | 
			
		||||
			if(!NativeLib.TransformKey256(pbNative, pbSeed, uRounds))
 | 
			
		||||
				return; // Native library not available ("success")
 | 
			
		||||
 | 
			
		||||
			if(!MemUtil.ArraysEqual(pbManaged, pbNative))
 | 
			
		||||
				throw new SecurityException("Native transform.");
 | 
			
		||||
				throw new SecurityException("AES-KDF-2");
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -252,12 +757,49 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
			pbN = enc.GetBytes("012b");
 | 
			
		||||
			if(MemUtil.IndexOf<byte>(pb, pbN) >= 0)
 | 
			
		||||
				throw new InvalidOperationException("MemUtil-7");
 | 
			
		||||
 | 
			
		||||
			byte[] pbRes = MemUtil.ParseBase32("MY======");
 | 
			
		||||
			byte[] pbExp = Encoding.ASCII.GetBytes("f");
 | 
			
		||||
			if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-1");
 | 
			
		||||
 | 
			
		||||
			pbRes = MemUtil.ParseBase32("MZXQ====");
 | 
			
		||||
			pbExp = Encoding.ASCII.GetBytes("fo");
 | 
			
		||||
			if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-2");
 | 
			
		||||
 | 
			
		||||
			pbRes = MemUtil.ParseBase32("MZXW6===");
 | 
			
		||||
			pbExp = Encoding.ASCII.GetBytes("foo");
 | 
			
		||||
			if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-3");
 | 
			
		||||
 | 
			
		||||
			pbRes = MemUtil.ParseBase32("MZXW6YQ=");
 | 
			
		||||
			pbExp = Encoding.ASCII.GetBytes("foob");
 | 
			
		||||
			if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-4");
 | 
			
		||||
 | 
			
		||||
			pbRes = MemUtil.ParseBase32("MZXW6YTB");
 | 
			
		||||
			pbExp = Encoding.ASCII.GetBytes("fooba");
 | 
			
		||||
			if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-5");
 | 
			
		||||
 | 
			
		||||
			pbRes = MemUtil.ParseBase32("MZXW6YTBOI======");
 | 
			
		||||
			pbExp = Encoding.ASCII.GetBytes("foobar");
 | 
			
		||||
			if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-6");
 | 
			
		||||
 | 
			
		||||
			pbRes = MemUtil.ParseBase32("JNSXSIDQOJXXM2LEMVZCAYTBONSWIIDPNYQG63TFFV2GS3LFEBYGC43TO5XXEZDTFY======");
 | 
			
		||||
			pbExp = Encoding.ASCII.GetBytes("Key provider based on one-time passwords.");
 | 
			
		||||
			if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-7");
 | 
			
		||||
 | 
			
		||||
			int i = 0 - 0x10203040;
 | 
			
		||||
			pbRes = MemUtil.Int32ToBytes(i);
 | 
			
		||||
			if(MemUtil.ByteArrayToHexString(pbRes) != "C0CFDFEF")
 | 
			
		||||
				throw new Exception("MemUtil-8"); // Must be little-endian
 | 
			
		||||
			if(MemUtil.BytesToUInt32(pbRes) != (uint)i)
 | 
			
		||||
				throw new Exception("MemUtil-9");
 | 
			
		||||
			if(MemUtil.BytesToInt32(pbRes) != i)
 | 
			
		||||
				throw new Exception("MemUtil-10");
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static void TestHmacOtp()
 | 
			
		||||
		{
 | 
			
		||||
#if (DEBUG && !KeePassLibSD && !KeePassRT)
 | 
			
		||||
#if (DEBUG && !KeePassLibSD)
 | 
			
		||||
			byte[] pbSecret = StrUtil.Utf8.GetBytes("12345678901234567890");
 | 
			
		||||
			string[] vExp = new string[]{ "755224", "287082", "359152",
 | 
			
		||||
				"969429", "338314", "254676", "287922", "162583", "399871",
 | 
			
		||||
@@ -325,6 +867,41 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
				throw new SecurityException("ProtectedString-8");
 | 
			
		||||
			if(!ps.IsProtected) throw new SecurityException("ProtectedString-9");
 | 
			
		||||
			if(!ps2.IsProtected) throw new SecurityException("ProtectedString-10");
 | 
			
		||||
 | 
			
		||||
			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
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -365,10 +942,16 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
				throw new InvalidOperationException("StrUtil-V3");
 | 
			
		||||
			if(StrUtil.VersionToString(0x00FF000000000000UL) != "255")
 | 
			
		||||
				throw new InvalidOperationException("StrUtil-V4");
 | 
			
		||||
			if(StrUtil.VersionToString(0x00FF000000000000UL, true) != "255.0")
 | 
			
		||||
			if(StrUtil.VersionToString(0x00FF000000000000UL, 2) != "255.0")
 | 
			
		||||
				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");
 | 
			
		||||
			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");
 | 
			
		||||
@@ -411,12 +994,22 @@ namespace KeePassLib.Cryptography
 | 
			
		||||
			if(short.MinValue.ToString(NumberFormatInfo.InvariantInfo) !=
 | 
			
		||||
				"-32768")
 | 
			
		||||
				throw new InvalidOperationException("StrUtil-Inv4");
 | 
			
		||||
 | 
			
		||||
			if(!string.Equals("abcd", "aBcd", StrUtil.CaseIgnoreCmp))
 | 
			
		||||
				throw new InvalidOperationException("StrUtil-Case1");
 | 
			
		||||
			if(string.Equals(@"a<b", @"a>b", StrUtil.CaseIgnoreCmp))
 | 
			
		||||
				throw new InvalidOperationException("StrUtil-Case2");
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static void TestUrlUtil()
 | 
			
		||||
		{
 | 
			
		||||
#if DEBUG
 | 
			
		||||
#if !KeePassUAP
 | 
			
		||||
			Debug.Assert(Uri.UriSchemeHttp.Equals("http", StrUtil.CaseIgnoreCmp));
 | 
			
		||||
			Debug.Assert(Uri.UriSchemeHttps.Equals("https", StrUtil.CaseIgnoreCmp));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
			if(UrlUtil.GetHost(@"scheme://domain:port/path?query_string#fragment_id") !=
 | 
			
		||||
				"domain")
 | 
			
		||||
				throw new InvalidOperationException("UrlUtil-H1");
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -39,18 +39,18 @@ namespace KeePassLib.Interfaces
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// The date/time when the object was last accessed.
 | 
			
		||||
		/// The date/time when the object was last modified.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		DateTime LastAccessTime
 | 
			
		||||
		DateTime LastModificationTime
 | 
			
		||||
		{
 | 
			
		||||
			get;
 | 
			
		||||
			set;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// The date/time when the object was last modified.
 | 
			
		||||
		/// The date/time when the object was last accessed.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		DateTime LastModificationTime
 | 
			
		||||
		DateTime LastAccessTime
 | 
			
		||||
		{
 | 
			
		||||
			get;
 | 
			
		||||
			set;
 | 
			
		||||
@@ -101,19 +101,5 @@ namespace KeePassLib.Interfaces
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		/// <param name="bModified">Update last modification time.</param>
 | 
			
		||||
		void Touch(bool bModified);
 | 
			
		||||
 | 
			
		||||
		#region Set times lazily
 | 
			
		||||
		// Passing xml datetime string to be parsed only on demand
 | 
			
		||||
 | 
			
		||||
		void SetLazyLastModificationTime(string xmlDateTime);
 | 
			
		||||
 | 
			
		||||
		void SetLazyCreationTime(string xmlDateTime);
 | 
			
		||||
 | 
			
		||||
		void SetLazyLastAccessTime(string xmlDateTime);
 | 
			
		||||
 | 
			
		||||
		void SetLazyExpiryTime(string xmlDateTime);
 | 
			
		||||
 | 
			
		||||
		void SetLazyLocationChanged(string xmlDateTime);
 | 
			
		||||
		#endregion
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -19,12 +19,11 @@
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Security.Cryptography;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using KeePassLib.Cryptography;
 | 
			
		||||
using KeePassLib.Security;
 | 
			
		||||
using KeePassLib.Utility;
 | 
			
		||||
 | 
			
		||||
namespace KeePassLib.Keys
 | 
			
		||||
{
 | 
			
		||||
@@ -55,8 +54,7 @@ namespace KeePassLib.Keys
 | 
			
		||||
 | 
			
		||||
			if(bPerformHash)
 | 
			
		||||
			{
 | 
			
		||||
				SHA256Managed sha256 = new SHA256Managed();
 | 
			
		||||
				byte[] pbRaw = sha256.ComputeHash(pbKeyData);
 | 
			
		||||
				byte[] pbRaw = CryptoUtil.HashSha256(pbKeyData);
 | 
			
		||||
				m_pbKey = new ProtectedBinary(true, pbRaw);
 | 
			
		||||
			}
 | 
			
		||||
			else m_pbKey = new ProtectedBinary(true, pbKeyData);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  
 | 
			
		||||
  Modified to be used with Mono for Android. Changes Copyright (C) 2013 Philipp Crocoll
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -65,7 +63,22 @@ namespace KeePassLib.Keys
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public KcpUserAccount()
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotSupportedException("DataProtection not supported on MonoForAndroid!");
 | 
			
		||||
			// Test if ProtectedData is supported -- throws an exception
 | 
			
		||||
			// when running on an old system (Windows 98 / ME).
 | 
			
		||||
			byte[] pbDummyData = new byte[128];
 | 
			
		||||
			ProtectedData.Protect(pbDummyData, m_pbEntropy,
 | 
			
		||||
				DataProtectionScope.CurrentUser);
 | 
			
		||||
 | 
			
		||||
			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()
 | 
			
		||||
@@ -75,8 +88,8 @@ namespace KeePassLib.Keys
 | 
			
		||||
 | 
			
		||||
		private static string GetUserKeyFilePath(bool bCreate)
 | 
			
		||||
		{
 | 
			
		||||
#if KeePassRT
 | 
			
		||||
			string strUserDir = Windows.Storage.ApplicationData.Current.RoamingFolder.Path;
 | 
			
		||||
#if KeePassUAP
 | 
			
		||||
			string strUserDir = EnvironmentExt.AppDataRoamingFolderPath;
 | 
			
		||||
#else
 | 
			
		||||
			string strUserDir = Environment.GetFolderPath(
 | 
			
		||||
				Environment.SpecialFolder.ApplicationData);
 | 
			
		||||
@@ -89,22 +102,25 @@ namespace KeePassLib.Keys
 | 
			
		||||
				Directory.CreateDirectory(strUserDir);
 | 
			
		||||
 | 
			
		||||
			strUserDir = UrlUtil.EnsureTerminatingSeparator(strUserDir, false);
 | 
			
		||||
			return strUserDir + UserKeyFileName;
 | 
			
		||||
			return (strUserDir + UserKeyFileName);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static byte[] LoadUserKey(bool bShowWarning)
 | 
			
		||||
		private static byte[] LoadUserKey(bool bThrow)
 | 
			
		||||
		{
 | 
			
		||||
			byte[] pbKey = null;
 | 
			
		||||
 | 
			
		||||
#if !KeePassLibSD
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
				throw new NotSupportedException("DataProtection not supported on MonoForAndroid!");
 | 
			
		||||
			}
 | 
			
		||||
			catch(Exception exLoad)
 | 
			
		||||
			{
 | 
			
		||||
				if(bShowWarning) MessageService.ShowWarning(exLoad);
 | 
			
		||||
				string strFilePath = GetUserKeyFilePath(false);
 | 
			
		||||
				byte[] pbProtectedKey = File.ReadAllBytes(strFilePath);
 | 
			
		||||
 | 
			
		||||
				pbKey = ProtectedData.Unprotect(pbProtectedKey, m_pbEntropy,
 | 
			
		||||
					DataProtectionScope.CurrentUser);
 | 
			
		||||
			}
 | 
			
		||||
			catch(Exception)
 | 
			
		||||
			{
 | 
			
		||||
				if(bThrow) throw;
 | 
			
		||||
				pbKey = null;
 | 
			
		||||
			}
 | 
			
		||||
#endif
 | 
			
		||||
@@ -114,17 +130,23 @@ namespace KeePassLib.Keys
 | 
			
		||||
 | 
			
		||||
		private static byte[] CreateUserKey()
 | 
			
		||||
		{
 | 
			
		||||
			byte[] pbKey = null;
 | 
			
		||||
#if KeePassLibSD
 | 
			
		||||
			return null;
 | 
			
		||||
#else
 | 
			
		||||
			string strFilePath = GetUserKeyFilePath(true);
 | 
			
		||||
 | 
			
		||||
#if !KeePassLibSD
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
				throw new NotSupportedException("DataProtection not supported on MonoForAndroid!");
 | 
			
		||||
			}
 | 
			
		||||
			catch(Exception) { pbKey = null; }
 | 
			
		||||
#endif
 | 
			
		||||
			byte[] pbRandomKey = CryptoRandom.Instance.GetRandomBytes(64);
 | 
			
		||||
			byte[] pbProtectedKey = ProtectedData.Protect(pbRandomKey,
 | 
			
		||||
				m_pbEntropy, DataProtectionScope.CurrentUser);
 | 
			
		||||
 | 
			
		||||
			File.WriteAllBytes(strFilePath, pbProtectedKey);
 | 
			
		||||
 | 
			
		||||
			byte[] pbKey = LoadUserKey(true);
 | 
			
		||||
			Debug.Assert(MemUtil.ArraysEqual(pbKey, pbRandomKey));
 | 
			
		||||
 | 
			
		||||
			MemUtil.ZeroByteArray(pbRandomKey);
 | 
			
		||||
			return pbKey;
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -27,7 +27,7 @@ using System.Runtime.InteropServices;
 | 
			
		||||
[assembly: AssemblyConfiguration("")]
 | 
			
		||||
[assembly: AssemblyCompany("Dominik Reichl")]
 | 
			
		||||
[assembly: AssemblyProduct("KeePassLib")]
 | 
			
		||||
[assembly: AssemblyCopyright("Copyright © 2003-2016 Dominik Reichl")]
 | 
			
		||||
[assembly: AssemblyCopyright("Copyright © 2003-2017 Dominik Reichl")]
 | 
			
		||||
[assembly: AssemblyTrademark("")]
 | 
			
		||||
[assembly: AssemblyCulture("")]
 | 
			
		||||
 | 
			
		||||
@@ -38,5 +38,5 @@ using System.Runtime.InteropServices;
 | 
			
		||||
[assembly: Guid("395f6eec-a1e0-4438-aa82-b75099348134")]
 | 
			
		||||
 | 
			
		||||
// Assembly version information
 | 
			
		||||
[assembly: AssemblyVersion("2.34.0.*")]
 | 
			
		||||
[assembly: AssemblyFileVersion("2.34.0.0")]
 | 
			
		||||
[assembly: AssemblyVersion("2.35.0.*")]
 | 
			
		||||
[assembly: AssemblyFileVersion("2.35.0.0")]
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -79,6 +79,7 @@ namespace KeePassLib
 | 
			
		||||
		private DateTime m_dtKeyLastChanged = PwDefs.DtDefaultNow;
 | 
			
		||||
		private long m_lKeyChangeRecDays = -1;
 | 
			
		||||
		private long m_lKeyChangeForceDays = -1;
 | 
			
		||||
		private bool m_bKeyChangeForceOnce = false;
 | 
			
		||||
 | 
			
		||||
		private IOConnectionInfo m_ioSource = new IOConnectionInfo();
 | 
			
		||||
		private bool m_bDatabaseOpened = false;
 | 
			
		||||
@@ -269,6 +270,12 @@ namespace KeePassLib
 | 
			
		||||
			set { m_lKeyChangeForceDays = value; }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool MasterKeyChangeForceOnce
 | 
			
		||||
		{
 | 
			
		||||
			get { return m_bKeyChangeForceOnce; }
 | 
			
		||||
			set { m_bKeyChangeForceOnce = value; }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// The encryption algorithm used to encrypt the data part of the database.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
@@ -537,7 +544,7 @@ namespace KeePassLib
 | 
			
		||||
			m_vCustomIcons = new List<PwCustomIcon>();
 | 
			
		||||
			m_bUINeedsIconUpdate = true;
 | 
			
		||||
 | 
			
		||||
			DateTime dtNow = DateTime.Now;
 | 
			
		||||
			DateTime dtNow = DateTime.UtcNow;
 | 
			
		||||
 | 
			
		||||
			m_dtSettingsChanged = dtNow;
 | 
			
		||||
			m_strName = string.Empty;
 | 
			
		||||
@@ -552,6 +559,7 @@ namespace KeePassLib
 | 
			
		||||
			m_dtKeyLastChanged = dtNow;
 | 
			
		||||
			m_lKeyChangeRecDays = -1;
 | 
			
		||||
			m_lKeyChangeForceDays = -1;
 | 
			
		||||
			m_bKeyChangeForceOnce = false;
 | 
			
		||||
 | 
			
		||||
			m_ioSource = new IOConnectionInfo();
 | 
			
		||||
			m_bDatabaseOpened = false;
 | 
			
		||||
@@ -1347,7 +1355,7 @@ namespace KeePassLib
 | 
			
		||||
			where T : class, ITimeLogger, IStructureItem, IDeepCloneable<T>
 | 
			
		||||
		{
 | 
			
		||||
			PwObjectPoolEx p = null;
 | 
			
		||||
			dtLoc = DateTime.MinValue;
 | 
			
		||||
			dtLoc = TimeUtil.SafeMinValueUtc;
 | 
			
		||||
 | 
			
		||||
			IStructureItem ptOrg = ppOrg.GetItemByUuid(t.Uuid);
 | 
			
		||||
			if(ptOrg != null)
 | 
			
		||||
@@ -1374,7 +1382,7 @@ namespace KeePassLib
 | 
			
		||||
			pPool = null;
 | 
			
		||||
 | 
			
		||||
			int iPosMax = kvpRange.Key;
 | 
			
		||||
			DateTime dtMax = DateTime.MinValue;
 | 
			
		||||
			DateTime dtMax = TimeUtil.SafeMinValueUtc;
 | 
			
		||||
 | 
			
		||||
			for(int i = kvpRange.Key; i <= kvpRange.Value; ++i)
 | 
			
		||||
			{
 | 
			
		||||
@@ -1885,7 +1893,7 @@ namespace KeePassLib
 | 
			
		||||
			if(m_bUseRecycleBin)
 | 
			
		||||
				pgRecycleBin = m_pgRootGroup.FindGroup(m_pwRecycleBin, true);
 | 
			
		||||
 | 
			
		||||
			DateTime dtNow = DateTime.Now;
 | 
			
		||||
			DateTime dtNow = DateTime.UtcNow;
 | 
			
		||||
			PwObjectList<PwEntry> l = m_pgRootGroup.GetEntries(true);
 | 
			
		||||
			int i = 0;
 | 
			
		||||
			while(true)
 | 
			
		||||
@@ -2010,7 +2018,7 @@ namespace KeePassLib
 | 
			
		||||
				if((pg.Groups.UCount > 0) || (pg.Entries.UCount > 0)) continue;
 | 
			
		||||
 | 
			
		||||
				pg.ParentGroup.Groups.Remove(pg);
 | 
			
		||||
				m_vDeletedObjects.Add(new PwDeletedObject(pg.Uuid, DateTime.Now));
 | 
			
		||||
				m_vDeletedObjects.Add(new PwDeletedObject(pg.Uuid, DateTime.UtcNow));
 | 
			
		||||
 | 
			
		||||
				++uDeleted;
 | 
			
		||||
			}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -55,20 +55,20 @@ namespace KeePassLib
 | 
			
		||||
		/// e.g. 2.19 = 0x02130000.
 | 
			
		||||
		/// It is highly recommended to use <c>FileVersion64</c> instead.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public const uint Version32 = 0x02220000;
 | 
			
		||||
		public const uint Version32 = 0x02230000;
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Version, encoded as 64-bit unsigned integer
 | 
			
		||||
		/// (component-wise, 16 bits per component).
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public const ulong FileVersion64 = 0x0002002200000000UL;
 | 
			
		||||
		public const ulong FileVersion64 = 0x0002002300000000UL;
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Version, encoded as string.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public const string VersionString = "2.34";
 | 
			
		||||
		public const string VersionString = "2.35";
 | 
			
		||||
 | 
			
		||||
		public const string Copyright = @"Copyright © 2003-2016 Dominik Reichl";
 | 
			
		||||
		public const string Copyright = @"Copyright © 2003-2017 Dominik Reichl";
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Product website URL. Terminated by a forward slash.
 | 
			
		||||
@@ -107,10 +107,11 @@ namespace KeePassLib
 | 
			
		||||
		/// A <c>DateTime</c> object that represents the time when the assembly
 | 
			
		||||
		/// was loaded.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public static readonly DateTime DtDefaultNow = DateTime.Now;
 | 
			
		||||
		public static readonly DateTime DtDefaultNow = DateTime.UtcNow;
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Default number of master key encryption/transformation rounds (making dictionary attacks harder).
 | 
			
		||||
		/// Default number of master key encryption/transformation rounds
 | 
			
		||||
		/// (making dictionary attacks harder).
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public const ulong DefaultKeyEncryptionRounds = 500000;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -343,8 +343,11 @@ namespace KeePassLib
 | 
			
		||||
 | 
			
		||||
			if(bSetTimes)
 | 
			
		||||
			{
 | 
			
		||||
				m_tCreation = m_tLastMod = m_tLastAccess =
 | 
			
		||||
					m_tParentGroupLastMod = DateTime.Now;
 | 
			
		||||
				DateTime dtNow = DateTime.UtcNow;
 | 
			
		||||
				m_tCreation = dtNow;
 | 
			
		||||
				m_tLastMod = dtNow;
 | 
			
		||||
				m_tLastAccess = dtNow;
 | 
			
		||||
				m_tParentGroupLastMod = dtNow;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -368,8 +371,11 @@ namespace KeePassLib
 | 
			
		||||
 | 
			
		||||
			if(bSetTimes)
 | 
			
		||||
			{
 | 
			
		||||
				m_tCreation = m_tLastMod = m_tLastAccess =
 | 
			
		||||
					m_tParentGroupLastMod = DateTime.Now;
 | 
			
		||||
				DateTime dtNow = DateTime.UtcNow;
 | 
			
		||||
				m_tCreation = dtNow;
 | 
			
		||||
				m_tLastMod = dtNow;
 | 
			
		||||
				m_tLastAccess = dtNow;
 | 
			
		||||
				m_tParentGroupLastMod = dtNow;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -622,7 +628,7 @@ namespace KeePassLib
 | 
			
		||||
		/// get touched, too.</param>
 | 
			
		||||
		public void Touch(bool bModified, bool bTouchParents)
 | 
			
		||||
		{
 | 
			
		||||
			m_tLastAccess = DateTime.Now;
 | 
			
		||||
			m_tLastAccess = DateTime.UtcNow;
 | 
			
		||||
			++m_uUsageCount;
 | 
			
		||||
 | 
			
		||||
			if(bModified) m_tLastMod = m_tLastAccess;
 | 
			
		||||
@@ -761,7 +767,7 @@ namespace KeePassLib
 | 
			
		||||
 | 
			
		||||
		private void RemoveOldestBackup()
 | 
			
		||||
		{
 | 
			
		||||
			DateTime dtMin = DateTime.MaxValue;
 | 
			
		||||
			DateTime dtMin = TimeUtil.SafeMaxValueUtc;
 | 
			
		||||
			uint idxRemove = uint.MaxValue;
 | 
			
		||||
 | 
			
		||||
			for(uint u = 0; u < m_listHistory.UCount; ++u)
 | 
			
		||||
@@ -936,7 +942,7 @@ namespace KeePassLib
 | 
			
		||||
 | 
			
		||||
		public void SetCreatedNow()
 | 
			
		||||
		{
 | 
			
		||||
			DateTime dt = DateTime.Now;
 | 
			
		||||
			DateTime dt = DateTime.UtcNow;
 | 
			
		||||
 | 
			
		||||
			m_tCreation = dt;
 | 
			
		||||
			m_tLastAccess = dt;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,9 @@ namespace KeePassLib.Resources
 | 
			
		||||
			m_strFatalError = TryGetEx(dictNew, "FatalError", m_strFatalError);
 | 
			
		||||
			m_strFatalErrorText = TryGetEx(dictNew, "FatalErrorText", m_strFatalErrorText);
 | 
			
		||||
			m_strFileCorrupted = TryGetEx(dictNew, "FileCorrupted", m_strFileCorrupted);
 | 
			
		||||
			m_strFileHeaderEndEarly = TryGetEx(dictNew, "FileHeaderEndEarly", m_strFileHeaderEndEarly);
 | 
			
		||||
			m_strFileHeaderCorrupted = TryGetEx(dictNew, "FileHeaderCorrupted", m_strFileHeaderCorrupted);
 | 
			
		||||
			m_strFileIncomplete = TryGetEx(dictNew, "FileIncomplete", m_strFileIncomplete);
 | 
			
		||||
			m_strFileIncompleteExpc = TryGetEx(dictNew, "FileIncompleteExpc", m_strFileIncompleteExpc);
 | 
			
		||||
			m_strFileLoadFailed = TryGetEx(dictNew, "FileLoadFailed", m_strFileLoadFailed);
 | 
			
		||||
			m_strFileLockedWrite = TryGetEx(dictNew, "FileLockedWrite", m_strFileLockedWrite);
 | 
			
		||||
			m_strFileNewVerOrPlgReq = TryGetEx(dictNew, "FileNewVerOrPlgReq", m_strFileNewVerOrPlgReq);
 | 
			
		||||
@@ -73,7 +75,9 @@ namespace KeePassLib.Resources
 | 
			
		||||
			"FatalError",
 | 
			
		||||
			"FatalErrorText",
 | 
			
		||||
			"FileCorrupted",
 | 
			
		||||
			"FileHeaderEndEarly",
 | 
			
		||||
			"FileHeaderCorrupted",
 | 
			
		||||
			"FileIncomplete",
 | 
			
		||||
			"FileIncompleteExpc",
 | 
			
		||||
			"FileLoadFailed",
 | 
			
		||||
			"FileLockedWrite",
 | 
			
		||||
			"FileNewVerOrPlgReq",
 | 
			
		||||
@@ -187,15 +191,37 @@ namespace KeePassLib.Resources
 | 
			
		||||
			get { return m_strFileCorrupted; }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static string m_strFileHeaderEndEarly =
 | 
			
		||||
			@"The file header is corrupted! Some header data was declared but is not present.";
 | 
			
		||||
		private static string m_strFileHeaderCorrupted =
 | 
			
		||||
			@"The file header is corrupted.";
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Look up a localized string similar to
 | 
			
		||||
		/// 'The file header is corrupted! Some header data was declared but is not present.'.
 | 
			
		||||
		/// 'The file header is corrupted.'.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public static string FileHeaderEndEarly
 | 
			
		||||
		public static string FileHeaderCorrupted
 | 
			
		||||
		{
 | 
			
		||||
			get { return m_strFileHeaderEndEarly; }
 | 
			
		||||
			get { return m_strFileHeaderCorrupted; }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static string m_strFileIncomplete =
 | 
			
		||||
			@"Data is missing at the end of the file, i.e. the file is incomplete.";
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Look up a localized string similar to
 | 
			
		||||
		/// 'Data is missing at the end of the file, i.e. the file is incomplete.'.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public static string FileIncomplete
 | 
			
		||||
		{
 | 
			
		||||
			get { return m_strFileIncomplete; }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static string m_strFileIncompleteExpc =
 | 
			
		||||
			@"Less data than expected could be read from the file.";
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Look up a localized string similar to
 | 
			
		||||
		/// 'Less data than expected could be read from the file.'.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public static string FileIncompleteExpc
 | 
			
		||||
		{
 | 
			
		||||
			get { return m_strFileIncompleteExpc; }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static string m_strFileLoadFailed =
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -165,7 +165,7 @@ namespace KeePassLib.Security
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public ProtectedBinary()
 | 
			
		||||
		{
 | 
			
		||||
			Init(false, MemUtil.EmptyByteArray);
 | 
			
		||||
			Init(false, MemUtil.EmptyByteArray, 0, 0);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
@@ -180,7 +180,27 @@ namespace KeePassLib.Security
 | 
			
		||||
		/// i.e. the caller is responsible for clearing it.</param>
 | 
			
		||||
		public ProtectedBinary(bool bEnableProtection, byte[] pbData)
 | 
			
		||||
		{
 | 
			
		||||
			Init(bEnableProtection, pbData);
 | 
			
		||||
			if(pbData == null) throw new ArgumentNullException("pbData");
 | 
			
		||||
 | 
			
		||||
			Init(bEnableProtection, pbData, 0, pbData.Length);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/// <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>
 | 
			
		||||
		/// <param name="iOffset">Offset for <paramref name="pbData" />.</param>
 | 
			
		||||
		/// <param name="cbSize">Size for <paramref name="pbData" />.</param>
 | 
			
		||||
		public ProtectedBinary(bool bEnableProtection, byte[] pbData,
 | 
			
		||||
			int iOffset, int cbSize)
 | 
			
		||||
		{
 | 
			
		||||
			Init(bEnableProtection, pbData, iOffset, cbSize);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
@@ -196,14 +216,19 @@ namespace KeePassLib.Security
 | 
			
		||||
			if(xbProtected == null) throw new ArgumentNullException("xbProtected");
 | 
			
		||||
 | 
			
		||||
			byte[] pb = xbProtected.ReadPlainText();
 | 
			
		||||
			Init(bEnableProtection, pb);
 | 
			
		||||
			Init(bEnableProtection, pb, 0, pb.Length);
 | 
			
		||||
 | 
			
		||||
			if(bEnableProtection) MemUtil.ZeroByteArray(pb);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void Init(bool bEnableProtection, byte[] pbData)
 | 
			
		||||
		private void Init(bool bEnableProtection, byte[] pbData, int iOffset,
 | 
			
		||||
			int cbSize)
 | 
			
		||||
		{
 | 
			
		||||
			if(pbData == null) throw new ArgumentNullException("pbData");
 | 
			
		||||
			if(iOffset < 0) throw new ArgumentOutOfRangeException("iOffset");
 | 
			
		||||
			if(cbSize < 0) throw new ArgumentOutOfRangeException("cbSize");
 | 
			
		||||
			if(iOffset > (pbData.Length - cbSize))
 | 
			
		||||
				throw new ArgumentOutOfRangeException("cbSize");
 | 
			
		||||
 | 
			
		||||
#if KeePassLibSD
 | 
			
		||||
			m_lID = ++g_lCurID;
 | 
			
		||||
@@ -212,15 +237,15 @@ namespace KeePassLib.Security
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
			m_bProtected = bEnableProtection;
 | 
			
		||||
			m_uDataLen = (uint)pbData.Length;
 | 
			
		||||
			m_uDataLen = (uint)cbSize;
 | 
			
		||||
 | 
			
		||||
			const int bs = ProtectedBinary.BlockSize;
 | 
			
		||||
			int nBlocks = (int)m_uDataLen / bs;
 | 
			
		||||
			if((nBlocks * bs) < (int)m_uDataLen) ++nBlocks;
 | 
			
		||||
			Debug.Assert((nBlocks * bs) >= (int)m_uDataLen);
 | 
			
		||||
			int nBlocks = cbSize / bs;
 | 
			
		||||
			if((nBlocks * bs) < cbSize) ++nBlocks;
 | 
			
		||||
			Debug.Assert((nBlocks * bs) >= cbSize);
 | 
			
		||||
 | 
			
		||||
			m_pbData = new byte[nBlocks * bs];
 | 
			
		||||
			Array.Copy(pbData, m_pbData, (int)m_uDataLen);
 | 
			
		||||
			Array.Copy(pbData, iOffset, m_pbData, 0, cbSize);
 | 
			
		||||
 | 
			
		||||
			Encrypt();
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -282,7 +282,7 @@ namespace KeePassLib.Security
 | 
			
		||||
			}
 | 
			
		||||
			finally
 | 
			
		||||
			{
 | 
			
		||||
				Array.Clear(v, 0, v.Length);
 | 
			
		||||
				MemUtil.ZeroArray<char>(v);
 | 
			
		||||
				MemUtil.ZeroByteArray(pb);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@@ -292,7 +292,7 @@ namespace KeePassLib.Security
 | 
			
		||||
			Debug.Assert(utf8.GetString(pbNew, 0, pbNew.Length) ==
 | 
			
		||||
				ReadString().Insert(iStart, strInsert));
 | 
			
		||||
 | 
			
		||||
			Array.Clear(vNew, 0, vNew.Length);
 | 
			
		||||
			MemUtil.ZeroArray<char>(vNew);
 | 
			
		||||
			MemUtil.ZeroByteArray(pbNew);
 | 
			
		||||
			return ps;
 | 
			
		||||
		}
 | 
			
		||||
@@ -328,7 +328,7 @@ namespace KeePassLib.Security
 | 
			
		||||
			}
 | 
			
		||||
			finally
 | 
			
		||||
			{
 | 
			
		||||
				Array.Clear(v, 0, v.Length);
 | 
			
		||||
				MemUtil.ZeroArray<char>(v);
 | 
			
		||||
				MemUtil.ZeroByteArray(pb);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@@ -338,7 +338,7 @@ namespace KeePassLib.Security
 | 
			
		||||
			Debug.Assert(utf8.GetString(pbNew, 0, pbNew.Length) ==
 | 
			
		||||
				ReadString().Remove(iStart, nCount));
 | 
			
		||||
 | 
			
		||||
			Array.Clear(vNew, 0, vNew.Length);
 | 
			
		||||
			MemUtil.ZeroArray<char>(vNew);
 | 
			
		||||
			MemUtil.ZeroByteArray(pbNew);
 | 
			
		||||
			return ps;
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -31,7 +31,7 @@ namespace KeePassLib.Serialization
 | 
			
		||||
		private Stream m_s;
 | 
			
		||||
		// private Encoding m_enc; // See constructor
 | 
			
		||||
 | 
			
		||||
		private string m_strReadExcp;
 | 
			
		||||
		private string m_strReadExcp; // May be null
 | 
			
		||||
		public string ReadExceptionText
 | 
			
		||||
		{
 | 
			
		||||
			get { return m_strReadExcp; }
 | 
			
		||||
@@ -67,7 +67,8 @@ namespace KeePassLib.Serialization
 | 
			
		||||
				byte[] pb = MemUtil.Read(m_s, nCount);
 | 
			
		||||
				if((pb == null) || (pb.Length != nCount))
 | 
			
		||||
				{
 | 
			
		||||
					if(m_strReadExcp != null) throw new IOException(m_strReadExcp);
 | 
			
		||||
					if(!string.IsNullOrEmpty(m_strReadExcp))
 | 
			
		||||
						throw new EndOfStreamException(m_strReadExcp);
 | 
			
		||||
					else throw new EndOfStreamException();
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
@@ -76,7 +77,8 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			}
 | 
			
		||||
			catch(Exception)
 | 
			
		||||
			{
 | 
			
		||||
				if(m_strReadExcp != null) throw new IOException(m_strReadExcp);
 | 
			
		||||
				if(!string.IsNullOrEmpty(m_strReadExcp))
 | 
			
		||||
					throw new IOException(m_strReadExcp);
 | 
			
		||||
				else throw;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -164,20 +164,9 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void Flush()
 | 
			
		||||
		{
 | 
			
		||||
			if(m_bWriting) m_bwOutput.Flush();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
#if KeePassUAP
 | 
			
		||||
		protected override void Dispose(bool disposing)
 | 
			
		||||
		{
 | 
			
		||||
			if(!disposing) return;
 | 
			
		||||
#else
 | 
			
		||||
		public override void Close()
 | 
			
		||||
		{
 | 
			
		||||
#endif
 | 
			
		||||
			if(m_sBaseStream != null)
 | 
			
		||||
			if(disposing && (m_sBaseStream != null))
 | 
			
		||||
		{
 | 
			
		||||
				if(!m_bWriting) // Reading mode
 | 
			
		||||
				{
 | 
			
		||||
@@ -202,6 +191,13 @@ namespace KeePassLib.Serialization
 | 
			
		||||
				m_sBaseStream.Close();
 | 
			
		||||
				m_sBaseStream = null;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			base.Dispose(disposing);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void Flush()
 | 
			
		||||
		{
 | 
			
		||||
			if(m_bWriting) m_bwOutput.Flush();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override long Seek(long lOffset, SeekOrigin soOrigin)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -98,21 +98,9 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void Flush()
 | 
			
		||||
		{
 | 
			
		||||
			Debug.Assert(m_sBase != null); // Object should not be disposed
 | 
			
		||||
			if(m_bWriting && (m_sBase != null)) m_sBase.Flush();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
#if KeePassUAP
 | 
			
		||||
		protected override void Dispose(bool disposing)
 | 
			
		||||
		{
 | 
			
		||||
			if(!disposing) return;
 | 
			
		||||
#else
 | 
			
		||||
		public override void Close()
 | 
			
		||||
		{
 | 
			
		||||
#endif
 | 
			
		||||
			if(m_sBase != null)
 | 
			
		||||
			if(disposing && (m_sBase != null))
 | 
			
		||||
			{
 | 
			
		||||
				if(m_bWriting)
 | 
			
		||||
				{
 | 
			
		||||
@@ -130,6 +118,14 @@ namespace KeePassLib.Serialization
 | 
			
		||||
				m_sBase.Close();
 | 
			
		||||
				m_sBase = null;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			base.Dispose(disposing);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void Flush()
 | 
			
		||||
		{
 | 
			
		||||
			Debug.Assert(m_sBase != null); // Object should not be disposed
 | 
			
		||||
			if(m_bWriting && (m_sBase != null)) m_sBase.Flush();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override long Seek(long lOffset, SeekOrigin soOrigin)
 | 
			
		||||
@@ -206,7 +202,8 @@ namespace KeePassLib.Serialization
 | 
			
		||||
 | 
			
		||||
			byte[] pbStoredHmac = MemUtil.Read(m_sBase, 32);
 | 
			
		||||
			if((pbStoredHmac == null) || (pbStoredHmac.Length != 32))
 | 
			
		||||
				throw new EndOfStreamException();
 | 
			
		||||
				throw new EndOfStreamException(KLRes.FileCorrupted + " " +
 | 
			
		||||
					KLRes.FileIncomplete);
 | 
			
		||||
 | 
			
		||||
			// Block index is implicit: it's used in the HMAC computation,
 | 
			
		||||
			// but does not need to be stored
 | 
			
		||||
@@ -220,7 +217,8 @@ namespace KeePassLib.Serialization
 | 
			
		||||
 | 
			
		||||
			byte[] pbBlockSize = MemUtil.Read(m_sBase, 4);
 | 
			
		||||
			if((pbBlockSize == null) || (pbBlockSize.Length != 4))
 | 
			
		||||
				throw new EndOfStreamException();
 | 
			
		||||
				throw new EndOfStreamException(KLRes.FileCorrupted + " " +
 | 
			
		||||
					KLRes.FileIncomplete);
 | 
			
		||||
			int nBlockSize = MemUtil.BytesToInt32(pbBlockSize);
 | 
			
		||||
			if(nBlockSize < 0)
 | 
			
		||||
				throw new InvalidDataException(KLRes.FileCorrupted);
 | 
			
		||||
@@ -229,7 +227,8 @@ namespace KeePassLib.Serialization
 | 
			
		||||
 | 
			
		||||
			m_pbBuffer = MemUtil.Read(m_sBase, nBlockSize);
 | 
			
		||||
			if((m_pbBuffer == null) || ((m_pbBuffer.Length != nBlockSize) && m_bVerify))
 | 
			
		||||
				throw new EndOfStreamException();
 | 
			
		||||
				throw new EndOfStreamException(KLRes.FileCorrupted + " " +
 | 
			
		||||
					KLRes.FileIncompleteExpc);
 | 
			
		||||
 | 
			
		||||
			if(m_bVerify)
 | 
			
		||||
			{
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  
 | 
			
		||||
  Modified to be used with Mono for Android. Changes Copyright (C) 2013 Philipp Crocoll
 | 
			
		||||
 | 
			
		||||
@@ -53,6 +53,185 @@ namespace KeePassLib.Serialization
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	internal abstract class WrapperStream : Stream
 | 
			
		||||
	{
 | 
			
		||||
		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;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
#if !KeePassUAP
 | 
			
		||||
		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);
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		protected override void Dispose(bool disposing)
 | 
			
		||||
		{
 | 
			
		||||
			if(disposing) m_s.Dispose();
 | 
			
		||||
 | 
			
		||||
			base.Dispose(disposing);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
#if !KeePassUAP
 | 
			
		||||
		public override int EndRead(IAsyncResult asyncResult)
 | 
			
		||||
		{
 | 
			
		||||
			return m_s.EndRead(asyncResult);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void EndWrite(IAsyncResult asyncResult)
 | 
			
		||||
		{
 | 
			
		||||
			m_s.EndWrite(asyncResult);
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		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
 | 
			
		||||
		private bool m_bDisposed = false;
 | 
			
		||||
 | 
			
		||||
		public IocStream(Stream sBase) : base(sBase)
 | 
			
		||||
		{
 | 
			
		||||
			m_bWrite = sBase.CanWrite;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		protected override void Dispose(bool disposing)
 | 
			
		||||
		{
 | 
			
		||||
			base.Dispose(disposing);
 | 
			
		||||
 | 
			
		||||
			if(disposing && MonoWorkarounds.IsRequired(10163) && m_bWrite &&
 | 
			
		||||
				!m_bDisposed)
 | 
			
		||||
			{
 | 
			
		||||
				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); }
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			m_bDisposed = true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static class IOConnection
 | 
			
		||||
	{
 | 
			
		||||
#if (!KeePassLibSD && !KeePassRT)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -132,7 +132,6 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			if(xr == null) throw new ArgumentNullException("xr");
 | 
			
		||||
 | 
			
		||||
			m_ctxGroups.Clear();
 | 
			
		||||
			m_dictBinPool = new Dictionary<string, ProtectedBinary>();
 | 
			
		||||
 | 
			
		||||
			KdbContext ctx = KdbContext.Null;
 | 
			
		||||
 | 
			
		||||
@@ -233,11 +232,11 @@ namespace KeePassLib.Serialization
 | 
			
		||||
						if(!string.IsNullOrEmpty(strHash) && (m_pbHashOfHeader != null) &&
 | 
			
		||||
							!m_bRepairMode)
 | 
			
		||||
						{
 | 
			
		||||
							Debug.Assert(m_uFileVersion <= FileVersion32_3);
 | 
			
		||||
							Debug.Assert(m_uFileVersion < FileVersion32_4);
 | 
			
		||||
 | 
			
		||||
							byte[] pbHash = Convert.FromBase64String(strHash);
 | 
			
		||||
							if(!MemUtil.ArraysEqual(pbHash, m_pbHashOfHeader))
 | 
			
		||||
								throw new IOException(KLRes.FileCorrupted);
 | 
			
		||||
								throw new InvalidDataException(KLRes.FileCorrupted);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					else if(xr.Name == ElemSettingsChanged)
 | 
			
		||||
@@ -268,6 +267,8 @@ namespace KeePassLib.Serialization
 | 
			
		||||
						m_pwDatabase.MasterKeyChangeRec = ReadLong(xr, -1);
 | 
			
		||||
					else if(xr.Name == ElemDbKeyChangeForce)
 | 
			
		||||
						m_pwDatabase.MasterKeyChangeForce = ReadLong(xr, -1);
 | 
			
		||||
					else if(xr.Name == ElemDbKeyChangeForceOnce)
 | 
			
		||||
						m_pwDatabase.MasterKeyChangeForceOnce = ReadBool(xr, false);
 | 
			
		||||
					else if(xr.Name == ElemMemoryProt)
 | 
			
		||||
						return SwitchContext(ctx, KdbContext.MemoryProtection, xr);
 | 
			
		||||
					else if(xr.Name == ElemCustomIcons)
 | 
			
		||||
@@ -340,7 +341,14 @@ namespace KeePassLib.Serialization
 | 
			
		||||
							string strKey = xr.Value;
 | 
			
		||||
							ProtectedBinary pbData = ReadProtectedBinary(xr);
 | 
			
		||||
 | 
			
		||||
							m_dictBinPool[strKey ?? string.Empty] = pbData;
 | 
			
		||||
							int iKey;
 | 
			
		||||
							if(!StrUtil.TryParseIntInvariant(strKey, out iKey))
 | 
			
		||||
								throw new FormatException();
 | 
			
		||||
							if(iKey < 0) throw new FormatException();
 | 
			
		||||
 | 
			
		||||
							Debug.Assert(m_pbsBinaries.Get(iKey) == null);
 | 
			
		||||
							Debug.Assert(m_pbsBinaries.Find(pbData) < 0);
 | 
			
		||||
							m_pbsBinaries.Set(iKey, pbData);
 | 
			
		||||
						}
 | 
			
		||||
						else ReadUnknown(xr);
 | 
			
		||||
					}
 | 
			
		||||
@@ -386,7 +394,7 @@ namespace KeePassLib.Serialization
 | 
			
		||||
					else if(xr.Name == ElemNotes)
 | 
			
		||||
						m_ctxGroup.Notes = ReadString(xr);
 | 
			
		||||
					else if(xr.Name == ElemIcon)
 | 
			
		||||
						m_ctxGroup.IconId = (PwIcon)ReadInt(xr, (int)PwIcon.Folder);
 | 
			
		||||
						m_ctxGroup.IconId = ReadIconId(xr, PwIcon.Folder);
 | 
			
		||||
					else if(xr.Name == ElemCustomIconID)
 | 
			
		||||
						m_ctxGroup.CustomIconUuid = ReadUuid(xr);
 | 
			
		||||
					else if(xr.Name == ElemTimes)
 | 
			
		||||
@@ -441,7 +449,7 @@ namespace KeePassLib.Serialization
 | 
			
		||||
					if(xr.Name == ElemUuid)
 | 
			
		||||
						m_ctxEntry.Uuid = ReadUuid(xr);
 | 
			
		||||
					else if(xr.Name == ElemIcon)
 | 
			
		||||
						m_ctxEntry.IconId = (PwIcon)ReadInt(xr, (int)PwIcon.Key);
 | 
			
		||||
						m_ctxEntry.IconId = ReadIconId(xr, PwIcon.Key);
 | 
			
		||||
					else if(xr.Name == ElemCustomIconID)
 | 
			
		||||
						m_ctxEntry.CustomIconUuid = ReadUuid(xr);
 | 
			
		||||
					else if(xr.Name == ElemFgColor)
 | 
			
		||||
@@ -848,16 +856,46 @@ namespace KeePassLib.Serialization
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private DateTime ReadTime(XmlReader xr)
 | 
			
		||||
		{
 | 
			
		||||
			// Cf. WriteObject(string, DateTime)
 | 
			
		||||
			if((m_format == KdbxFormat.Default) && (m_uFileVersion >= FileVersion32_4))
 | 
			
		||||
			{
 | 
			
		||||
				// long l = ReadLong(xr, -1);
 | 
			
		||||
				// if(l != -1) return DateTime.FromBinary(l);
 | 
			
		||||
 | 
			
		||||
				string str = ReadString(xr);
 | 
			
		||||
				byte[] pb = Convert.FromBase64String(str);
 | 
			
		||||
				if(pb.Length != 8)
 | 
			
		||||
				{
 | 
			
		||||
					Debug.Assert(false);
 | 
			
		||||
					byte[] pb8 = new byte[8];
 | 
			
		||||
					Array.Copy(pb, pb8, Math.Min(pb.Length, 8)); // Little-endian
 | 
			
		||||
					pb = pb8;
 | 
			
		||||
				}
 | 
			
		||||
				long lSec = MemUtil.BytesToInt64(pb);
 | 
			
		||||
				return new DateTime(lSec * TimeSpan.TicksPerSecond, DateTimeKind.Utc);
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				string str = ReadString(xr);
 | 
			
		||||
 | 
			
		||||
				DateTime dt;
 | 
			
		||||
				if(TimeUtil.TryDeserializeUtc(str, out dt)) return dt;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			Debug.Assert(false);
 | 
			
		||||
			return m_dtNow;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private PwIcon ReadIconId(XmlReader xr, PwIcon icDefault)
 | 
			
		||||
		{
 | 
			
		||||
			int i = ReadInt(xr, (int)icDefault);
 | 
			
		||||
			if((i >= 0) && (i < (int)PwIcon.Count)) return (PwIcon)i;
 | 
			
		||||
 | 
			
		||||
			Debug.Assert(false);
 | 
			
		||||
			return icDefault;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private ProtectedString ReadProtectedString(XmlReader xr)
 | 
			
		||||
		{
 | 
			
		||||
			XorredBuffer xb = ProcessNode(xr);
 | 
			
		||||
@@ -882,9 +920,12 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			if(xr.MoveToAttribute(AttrRef))
 | 
			
		||||
			{
 | 
			
		||||
				string strRef = xr.Value;
 | 
			
		||||
				if(strRef != null)
 | 
			
		||||
				if(!string.IsNullOrEmpty(strRef))
 | 
			
		||||
				{
 | 
			
		||||
					ProtectedBinary pb = BinPoolGet(strRef);
 | 
			
		||||
					int iRef;
 | 
			
		||||
					if(StrUtil.TryParseIntInvariant(strRef, out iRef))
 | 
			
		||||
					{
 | 
			
		||||
						ProtectedBinary pb = m_pbsBinaries.Get(iRef);
 | 
			
		||||
						if(pb != null)
 | 
			
		||||
						{
 | 
			
		||||
							// https://sourceforge.net/p/keepass/feature-requests/2023/
 | 
			
		||||
@@ -902,6 +943,8 @@ namespace KeePassLib.Serialization
 | 
			
		||||
					}
 | 
			
		||||
					else { Debug.Assert(false); }
 | 
			
		||||
				}
 | 
			
		||||
				else { Debug.Assert(false); }
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			bool bCompressed = false;
 | 
			
		||||
			if(xr.MoveToAttribute(AttrCompressed))
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,8 @@
 | 
			
		||||
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
// #define KDBX_BENCHMARK
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
@@ -42,6 +44,7 @@ using KeePassLib.Cryptography.KeyDerivation;
 | 
			
		||||
using KeePassLib.Interfaces;
 | 
			
		||||
using KeePassLib.Keys;
 | 
			
		||||
using KeePassLib.Resources;
 | 
			
		||||
using KeePassLib.Security;
 | 
			
		||||
using KeePassLib.Utility;
 | 
			
		||||
 | 
			
		||||
using keepass2android;
 | 
			
		||||
@@ -77,9 +80,19 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			Debug.Assert(sSource != null);
 | 
			
		||||
			if(sSource == null) throw new ArgumentNullException("sSource");
 | 
			
		||||
 | 
			
		||||
			if(m_bUsedOnce)
 | 
			
		||||
				throw new InvalidOperationException("Do not reuse KdbxFile objects!");
 | 
			
		||||
			m_bUsedOnce = true;
 | 
			
		||||
 | 
			
		||||
#if KDBX_BENCHMARK
 | 
			
		||||
			Stopwatch swTime = Stopwatch.StartNew();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
			m_format = fmt;
 | 
			
		||||
			m_slLogger = slLogger;
 | 
			
		||||
 | 
			
		||||
			m_pbsBinaries.Clear();
 | 
			
		||||
 | 
			
		||||
			UTF8Encoding encNoBom = StrUtil.Utf8;
 | 
			
		||||
			byte[] pbCipherKey = null;
 | 
			
		||||
			byte[] pbHmacKey64 = null;
 | 
			
		||||
@@ -98,6 +111,7 @@ namespace KeePassLib.Serialization
 | 
			
		||||
					BinaryReaderEx br = new BinaryReaderEx(sHashing,
 | 
			
		||||
						encNoBom, KLRes.FileCorrupted);
 | 
			
		||||
					byte[] pbHeader = LoadHeader(br);
 | 
			
		||||
					m_pbHashOfHeader = CryptoUtil.HashSha256(pbHeader);
 | 
			
		||||
 | 
			
		||||
					int cbEncKey, cbEncIV;
 | 
			
		||||
					ICipherEngine iCipher = GetCipher(out cbEncKey, out cbEncIV);
 | 
			
		||||
@@ -107,8 +121,11 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			
 | 
			
		||||
					ComputeKeys(out pbCipherKey, cbEncKey, out pbHmacKey64);
 | 
			
		||||
 | 
			
		||||
					string strIncomplete = KLRes.FileHeaderCorrupted + " " +
 | 
			
		||||
						KLRes.FileIncomplete;
 | 
			
		||||
 | 
			
		||||
					Stream sPlain;
 | 
			
		||||
					if(m_uFileVersion <= FileVersion32_3)
 | 
			
		||||
					if(m_uFileVersion < FileVersion32_4)
 | 
			
		||||
					{
 | 
			
		||||
						Stream sDecrypted = EncryptStream(sHashing, iCipher,
 | 
			
		||||
							pbCipherKey, cbEncIV, false);
 | 
			
		||||
@@ -121,11 +138,11 @@ namespace KeePassLib.Serialization
 | 
			
		||||
						lStreams.Add(sDecrypted);
 | 
			
		||||
 | 
			
		||||
						BinaryReaderEx brDecrypted = new BinaryReaderEx(sDecrypted,
 | 
			
		||||
							encNoBom, KLRes.FileCorrupted);
 | 
			
		||||
							encNoBom, strIncomplete);
 | 
			
		||||
						byte[] pbStoredStartBytes = brDecrypted.ReadBytes(32);
 | 
			
		||||
 | 
			
		||||
						if((m_pbStreamStartBytes == null) || (m_pbStreamStartBytes.Length != 32))
 | 
			
		||||
							throw new InvalidDataException();
 | 
			
		||||
							throw new EndOfStreamException(strIncomplete);
 | 
			
		||||
						if(!MemUtil.ArraysEqual(pbStoredStartBytes, m_pbStreamStartBytes))
 | 
			
		||||
							throw new InvalidCompositeKeyException();
 | 
			
		||||
 | 
			
		||||
@@ -137,10 +154,16 @@ namespace KeePassLib.Serialization
 | 
			
		||||
					}
 | 
			
		||||
					else // KDBX >= 4
 | 
			
		||||
					{
 | 
			
		||||
						byte[] pbStoredHash = MemUtil.Read(sHashing, 32);
 | 
			
		||||
						if((pbStoredHash == null) || (pbStoredHash.Length != 32))
 | 
			
		||||
							throw new EndOfStreamException(strIncomplete);
 | 
			
		||||
						if(!MemUtil.ArraysEqual(m_pbHashOfHeader, pbStoredHash))
 | 
			
		||||
							throw new InvalidDataException(KLRes.FileHeaderCorrupted);
 | 
			
		||||
 | 
			
		||||
						byte[] pbHeaderHmac = ComputeHeaderHmac(pbHeader, pbHmacKey64);
 | 
			
		||||
						byte[] pbStoredHmac = MemUtil.Read(sHashing, 32);
 | 
			
		||||
						if((pbStoredHmac == null) || (pbStoredHmac.Length != 32))
 | 
			
		||||
							throw new InvalidDataException();
 | 
			
		||||
							throw new EndOfStreamException(strIncomplete);
 | 
			
		||||
						if(!MemUtil.ArraysEqual(pbHeaderHmac, pbStoredHmac))
 | 
			
		||||
							throw new InvalidCompositeKeyException();
 | 
			
		||||
 | 
			
		||||
@@ -161,6 +184,9 @@ namespace KeePassLib.Serialization
 | 
			
		||||
						lStreams.Add(sXml);
 | 
			
		||||
					}
 | 
			
		||||
					else sXml = sPlain;
 | 
			
		||||
 | 
			
		||||
					if(m_uFileVersion >= FileVersion32_4)
 | 
			
		||||
						LoadInnerHeader(sXml); // Binary header before XML
 | 
			
		||||
				}
 | 
			
		||||
				else if(fmt == KdbxFormat.PlainXml)
 | 
			
		||||
					sXml = sHashing;
 | 
			
		||||
@@ -168,16 +194,15 @@ namespace KeePassLib.Serialization
 | 
			
		||||
 | 
			
		||||
				if(fmt == KdbxFormat.Default)
 | 
			
		||||
				{
 | 
			
		||||
					if(m_pbProtectedStreamKey == null)
 | 
			
		||||
					if(m_pbInnerRandomStreamKey == null)
 | 
			
		||||
					{
 | 
			
		||||
						Debug.Assert(false);
 | 
			
		||||
						throw new SecurityException("Invalid protected stream key!");
 | 
			
		||||
						throw new SecurityException("Invalid inner random stream key!");
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					m_randomStream = new CryptoRandomStream(m_craInnerRandomStream,
 | 
			
		||||
						m_pbProtectedStreamKey);
 | 
			
		||||
						m_pbInnerRandomStreamKey);
 | 
			
		||||
				}
 | 
			
		||||
				else m_randomStream = null; // No random stream for plain-text files
 | 
			
		||||
				if (m_slLogger != null)
 | 
			
		||||
					m_slLogger.SetText("KP2AKEY_ParsingDatabase", LogStatusType.AdditionalInfo);
 | 
			
		||||
				
 | 
			
		||||
@@ -225,6 +250,12 @@ namespace KeePassLib.Serialization
 | 
			
		||||
 | 
			
		||||
				CommonCleanUpRead(lStreams, sHashing);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
#if KDBX_BENCHMARK
 | 
			
		||||
			swTime.Stop();
 | 
			
		||||
			MessageService.ShowInfo("Loading KDBX took " +
 | 
			
		||||
				swTime.ElapsedMilliseconds.ToString() + " ms.");
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void CommonCleanUpRead(List<Stream> lStreams, HashingStreamEx sHashing)
 | 
			
		||||
@@ -235,8 +266,10 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			m_pbHashOfFileOnDisk = sHashing.Hash;
 | 
			
		||||
			Debug.Assert(m_pbHashOfFileOnDisk != null);
 | 
			
		||||
 | 
			
		||||
			CleanUpInnerRandomStream();
 | 
			
		||||
			// Reset memory protection settings (to always use reasonable
 | 
			
		||||
			// defaults)
 | 
			
		||||
			// defaults)
 | 
			
		||||
			m_pwDatabase.MemoryProtection = new MemoryProtectionConfig();
 | 
			
		||||
 | 
			
		||||
			// Remove old backups (this call is required here in order to apply
 | 
			
		||||
@@ -257,6 +290,10 @@ namespace KeePassLib.Serialization
 | 
			
		||||
 | 
			
		||||
		private byte[] LoadHeader(BinaryReaderEx br)
 | 
			
		||||
		{
 | 
			
		||||
			string strPrevExcpText = br.ReadExceptionText;
 | 
			
		||||
			br.ReadExceptionText = KLRes.FileHeaderCorrupted + " " +
 | 
			
		||||
				KLRes.FileIncompleteExpc;
 | 
			
		||||
 | 
			
		||||
			MemoryStream msHeader = new MemoryStream();
 | 
			
		||||
			Debug.Assert(br.CopyDataTo == null);
 | 
			
		||||
			br.CopyDataTo = msHeader;
 | 
			
		||||
@@ -291,7 +328,7 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			byte[] pbHeader = msHeader.ToArray();
 | 
			
		||||
			msHeader.Close();
 | 
			
		||||
 | 
			
		||||
			m_pbHashOfHeader = CryptoUtil.HashSha256(pbHeader);
 | 
			
		||||
			br.ReadExceptionText = strPrevExcpText;
 | 
			
		||||
			return pbHeader;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -304,21 +341,13 @@ namespace KeePassLib.Serialization
 | 
			
		||||
 | 
			
		||||
			int cbSize;
 | 
			
		||||
			Debug.Assert(m_uFileVersion > 0);
 | 
			
		||||
			if(m_uFileVersion <= FileVersion32_3)
 | 
			
		||||
			if(m_uFileVersion < FileVersion32_4)
 | 
			
		||||
				cbSize = (int)MemUtil.BytesToUInt16(brSource.ReadBytes(2));
 | 
			
		||||
			else cbSize = MemUtil.BytesToInt32(brSource.ReadBytes(4));
 | 
			
		||||
			if(cbSize < 0) throw new FormatException(KLRes.FileCorrupted);
 | 
			
		||||
 | 
			
		||||
			byte[] pbData = MemUtil.EmptyByteArray;
 | 
			
		||||
			if(cbSize > 0)
 | 
			
		||||
			{
 | 
			
		||||
				string strPrevExcpText = brSource.ReadExceptionText;
 | 
			
		||||
				brSource.ReadExceptionText = KLRes.FileHeaderEndEarly;
 | 
			
		||||
 | 
			
		||||
				pbData = brSource.ReadBytes(cbSize);
 | 
			
		||||
 | 
			
		||||
				brSource.ReadExceptionText = strPrevExcpText;
 | 
			
		||||
			}
 | 
			
		||||
			if(cbSize > 0) pbData = brSource.ReadBytes(cbSize);
 | 
			
		||||
 | 
			
		||||
			bool bResult = true;
 | 
			
		||||
			KdbxHeaderFieldID kdbID = (KdbxHeaderFieldID)btFieldID;
 | 
			
		||||
@@ -343,6 +372,8 @@ namespace KeePassLib.Serialization
 | 
			
		||||
 | 
			
		||||
				// Obsolete; for backward compatibility only
 | 
			
		||||
				case KdbxHeaderFieldID.TransformSeed:
 | 
			
		||||
					Debug.Assert(m_uFileVersion < FileVersion32_4);
 | 
			
		||||
 | 
			
		||||
					AesKdf kdfS = new AesKdf();
 | 
			
		||||
					if(!m_pwDatabase.KdfParameters.KdfUuid.Equals(kdfS.Uuid))
 | 
			
		||||
						m_pwDatabase.KdfParameters = kdfS.GetDefaultParameters();
 | 
			
		||||
@@ -355,6 +386,8 @@ namespace KeePassLib.Serialization
 | 
			
		||||
 | 
			
		||||
				// Obsolete; for backward compatibility only
 | 
			
		||||
				case KdbxHeaderFieldID.TransformRounds:
 | 
			
		||||
					Debug.Assert(m_uFileVersion < FileVersion32_4);
 | 
			
		||||
 | 
			
		||||
					AesKdf kdfR = new AesKdf();
 | 
			
		||||
					if(!m_pwDatabase.KdfParameters.KdfUuid.Equals(kdfR.Uuid))
 | 
			
		||||
						m_pwDatabase.KdfParameters = kdfR.GetDefaultParameters();
 | 
			
		||||
@@ -368,17 +401,20 @@ namespace KeePassLib.Serialization
 | 
			
		||||
					m_pbEncryptionIV = pbData;
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				case KdbxHeaderFieldID.ProtectedStreamKey:
 | 
			
		||||
					m_pbProtectedStreamKey = pbData;
 | 
			
		||||
				case KdbxHeaderFieldID.InnerRandomStreamKey:
 | 
			
		||||
					Debug.Assert(m_uFileVersion < FileVersion32_4);
 | 
			
		||||
					Debug.Assert(m_pbInnerRandomStreamKey == null);
 | 
			
		||||
					m_pbInnerRandomStreamKey = pbData;
 | 
			
		||||
					CryptoRandom.Instance.AddEntropy(pbData);
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				case KdbxHeaderFieldID.StreamStartBytes:
 | 
			
		||||
					Debug.Assert(m_uFileVersion <= FileVersion32_3);
 | 
			
		||||
					Debug.Assert(m_uFileVersion < FileVersion32_4);
 | 
			
		||||
					m_pbStreamStartBytes = pbData;
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				case KdbxHeaderFieldID.InnerRandomStreamID:
 | 
			
		||||
					Debug.Assert(m_uFileVersion < FileVersion32_4);
 | 
			
		||||
					SetInnerRandomStreamID(pbData);
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
@@ -402,6 +438,68 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			return bResult;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void LoadInnerHeader(Stream s)
 | 
			
		||||
		{
 | 
			
		||||
			BinaryReaderEx br = new BinaryReaderEx(s, StrUtil.Utf8,
 | 
			
		||||
				KLRes.FileCorrupted + " " + KLRes.FileIncompleteExpc);
 | 
			
		||||
 | 
			
		||||
			while(true)
 | 
			
		||||
			{
 | 
			
		||||
				if(!ReadInnerHeaderField(br)) break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private bool ReadInnerHeaderField(BinaryReaderEx br)
 | 
			
		||||
		{
 | 
			
		||||
			Debug.Assert(br != null);
 | 
			
		||||
			if(br == null) throw new ArgumentNullException("br");
 | 
			
		||||
 | 
			
		||||
			byte btFieldID = br.ReadByte();
 | 
			
		||||
 | 
			
		||||
			int cbSize = MemUtil.BytesToInt32(br.ReadBytes(4));
 | 
			
		||||
			if(cbSize < 0) throw new FormatException(KLRes.FileCorrupted);
 | 
			
		||||
 | 
			
		||||
			byte[] pbData = MemUtil.EmptyByteArray;
 | 
			
		||||
			if(cbSize > 0) pbData = br.ReadBytes(cbSize);
 | 
			
		||||
 | 
			
		||||
			bool bResult = true;
 | 
			
		||||
			KdbxInnerHeaderFieldID kdbID = (KdbxInnerHeaderFieldID)btFieldID;
 | 
			
		||||
			switch(kdbID)
 | 
			
		||||
			{
 | 
			
		||||
				case KdbxInnerHeaderFieldID.EndOfHeader:
 | 
			
		||||
					bResult = false; // Returning false indicates end of header
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				case KdbxInnerHeaderFieldID.InnerRandomStreamID:
 | 
			
		||||
					SetInnerRandomStreamID(pbData);
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				case KdbxInnerHeaderFieldID.InnerRandomStreamKey:
 | 
			
		||||
					Debug.Assert(m_pbInnerRandomStreamKey == null);
 | 
			
		||||
					m_pbInnerRandomStreamKey = pbData;
 | 
			
		||||
					CryptoRandom.Instance.AddEntropy(pbData);
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				case KdbxInnerHeaderFieldID.Binary:
 | 
			
		||||
					if(pbData.Length < 1) throw new FormatException();
 | 
			
		||||
					KdbxBinaryFlags f = (KdbxBinaryFlags)pbData[0];
 | 
			
		||||
					bool bProt = ((f & KdbxBinaryFlags.Protected) != KdbxBinaryFlags.None);
 | 
			
		||||
 | 
			
		||||
					ProtectedBinary pb = new ProtectedBinary(bProt, pbData,
 | 
			
		||||
						1, pbData.Length - 1);
 | 
			
		||||
					m_pbsBinaries.Add(pb);
 | 
			
		||||
 | 
			
		||||
					if(bProt) MemUtil.ZeroByteArray(pbData);
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				default:
 | 
			
		||||
					Debug.Assert(false);
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return bResult;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void SetCipher(byte[] pbID)
 | 
			
		||||
		{
 | 
			
		||||
			if((pbID == null) || (pbID.Length != (int)PwUuid.UuidSize))
 | 
			
		||||
@@ -429,19 +527,31 @@ namespace KeePassLib.Serialization
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		[Obsolete]
 | 
			
		||||
		public static List<PwEntry> ReadEntries(PwDatabase pwDatabase, Stream msData)
 | 
			
		||||
		public static List<PwEntry> ReadEntries(Stream msData)
 | 
			
		||||
		{
 | 
			
		||||
			return ReadEntries(msData);
 | 
			
		||||
			return ReadEntries(msData, null, false);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		[Obsolete]
 | 
			
		||||
		public static List<PwEntry> ReadEntries(PwDatabase pdContext, Stream msData)
 | 
			
		||||
		{
 | 
			
		||||
			return ReadEntries(msData, pdContext, true);
 | 
			
		||||
		}
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Read entries from a stream.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		/// <param name="msData">Input stream to read the entries from.</param>
 | 
			
		||||
		/// <returns>Extracted entries.</returns>
 | 
			
		||||
		public static List<PwEntry> ReadEntries(Stream msData)
 | 
			
		||||
		/// <param name="pdContext">Context database (e.g. for storing icons).</param>
 | 
			
		||||
		/// <param name="bCopyIcons">If <c>true</c>, custom icons required by
 | 
			
		||||
		/// the loaded entries are copied to the context database.</param>
 | 
			
		||||
		/// <returns>Loaded entries.</returns>
 | 
			
		||||
		public static List<PwEntry> ReadEntries(Stream msData, PwDatabase pdContext,
 | 
			
		||||
			bool bCopyIcons)
 | 
			
		||||
		{
 | 
			
		||||
			List<PwEntry> lEntries = new List<PwEntry>();
 | 
			
		||||
			/* KdbxFile f = new KdbxFile(pwDatabase);
 | 
			
		||||
			if(msData == null) { Debug.Assert(false); return lEntries; }
 | 
			
		||||
			f.m_format = KdbxFormat.PlainXml;
 | 
			
		||||
 | 
			
		||||
			XmlDocument doc = new XmlDocument();
 | 
			
		||||
@@ -467,20 +577,43 @@ namespace KeePassLib.Serialization
 | 
			
		||||
				else { Debug.Assert(false); }
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return vEntries; */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
			return vEntries; */
 | 
			
		||||
 | 
			
		||||
			PwDatabase pd = new PwDatabase();
 | 
			
		||||
			pd.New(new IOConnectionInfo(), new CompositeKey());
 | 
			
		||||
 | 
			
		||||
			KdbxFile f = new KdbxFile(pd);
 | 
			
		||||
			f.Load(msData, KdbxFormat.PlainXml, null);
 | 
			
		||||
 | 
			
		||||
			List<PwEntry> vEntries = new List<PwEntry>();
 | 
			
		||||
			foreach(PwEntry pe in pd.RootGroup.Entries)
 | 
			
		||||
			{
 | 
			
		||||
				pe.SetUuid(new PwUuid(true), true);
 | 
			
		||||
				vEntries.Add(pe);
 | 
			
		||||
				lEntries.Add(pe);
 | 
			
		||||
 | 
			
		||||
				if(bCopyIcons && (pdContext != null))
 | 
			
		||||
				{
 | 
			
		||||
					PwUuid pu = pe.CustomIconUuid;
 | 
			
		||||
					if(!pu.Equals(PwUuid.Zero))
 | 
			
		||||
					{
 | 
			
		||||
						int iSrc = pd.GetCustomIconIndex(pu);
 | 
			
		||||
						int iDst = pdContext.GetCustomIconIndex(pu);
 | 
			
		||||
 | 
			
		||||
						if(iSrc < 0) { Debug.Assert(false); }
 | 
			
		||||
						else if(iDst < 0)
 | 
			
		||||
						{
 | 
			
		||||
							pdContext.CustomIcons.Add(pd.CustomIcons[iSrc]);
 | 
			
		||||
 | 
			
		||||
							pdContext.Modified = true;
 | 
			
		||||
							pdContext.UINeedsIconUpdate = true;
 | 
			
		||||
			}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return vEntries;
 | 
			
		||||
			return lEntries;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -83,14 +83,22 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			Debug.Assert(sSaveTo != null);
 | 
			
		||||
			if(sSaveTo == null) throw new ArgumentNullException("sSaveTo");
 | 
			
		||||
 | 
			
		||||
			if(m_bUsedOnce)
 | 
			
		||||
				throw new InvalidOperationException("Do not reuse KdbxFile objects!");
 | 
			
		||||
			m_bUsedOnce = true;
 | 
			
		||||
 | 
			
		||||
			m_format = fmt;
 | 
			
		||||
			m_slLogger = slLogger;
 | 
			
		||||
 | 
			
		||||
			PwGroup pgRoot = (pgDataSource ?? m_pwDatabase.RootGroup);
 | 
			
		||||
			UTF8Encoding encNoBom = StrUtil.Utf8;
 | 
			
		||||
			CryptoRandom cr = CryptoRandom.Instance;
 | 
			
		||||
			byte[] pbCipherKey = null;
 | 
			
		||||
			byte[] pbHmacKey64 = null;
 | 
			
		||||
 | 
			
		||||
			m_pbsBinaries.Clear();
 | 
			
		||||
			m_pbsBinaries.AddFrom(pgRoot);
 | 
			
		||||
 | 
			
		||||
			List<Stream> lStreams = new List<Stream>();
 | 
			
		||||
			lStreams.Add(sSaveTo);
 | 
			
		||||
 | 
			
		||||
@@ -116,20 +124,24 @@ namespace KeePassLib.Serialization
 | 
			
		||||
						"UUID: " + puKdf.ToHexString() + ".");
 | 
			
		||||
				kdf.Randomize(m_pwDatabase.KdfParameters);
 | 
			
		||||
 | 
			
		||||
				if(m_uFileVersion <= FileVersion32_3)
 | 
			
		||||
				if(m_format == KdbxFormat.Default)
 | 
			
		||||
				{
 | 
			
		||||
					if(m_uFileVersion < FileVersion32_4)
 | 
			
		||||
					{
 | 
			
		||||
					m_craInnerRandomStream = CrsAlgorithm.Salsa20;
 | 
			
		||||
					m_pbProtectedStreamKey = cr.GetRandomBytes(32);
 | 
			
		||||
						m_pbInnerRandomStreamKey = cr.GetRandomBytes(32);
 | 
			
		||||
				}
 | 
			
		||||
				else // KDBX >= 4
 | 
			
		||||
				{
 | 
			
		||||
					m_craInnerRandomStream = CrsAlgorithm.ChaCha20;
 | 
			
		||||
					m_pbProtectedStreamKey = cr.GetRandomBytes(64);
 | 
			
		||||
						m_pbInnerRandomStreamKey = cr.GetRandomBytes(64);
 | 
			
		||||
				}
 | 
			
		||||
				m_randomStream = new CryptoRandomStream(m_craInnerRandomStream,
 | 
			
		||||
					m_pbProtectedStreamKey);
 | 
			
		||||
 | 
			
		||||
				if(m_uFileVersion <= FileVersion32_3)
 | 
			
		||||
				m_randomStream = new CryptoRandomStream(m_craInnerRandomStream,
 | 
			
		||||
						m_pbInnerRandomStreamKey);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if(m_uFileVersion < FileVersion32_4)
 | 
			
		||||
					m_pbStreamStartBytes = cr.GetRandomBytes(32);
 | 
			
		||||
 | 
			
		||||
				Stream sXml;
 | 
			
		||||
@@ -144,7 +156,7 @@ namespace KeePassLib.Serialization
 | 
			
		||||
					ComputeKeys(out pbCipherKey, cbEncKey, out pbHmacKey64);
 | 
			
		||||
 | 
			
		||||
					Stream sPlain;
 | 
			
		||||
					if(m_uFileVersion <= FileVersion32_3)
 | 
			
		||||
					if(m_uFileVersion < FileVersion32_4)
 | 
			
		||||
					{
 | 
			
		||||
						Stream sEncrypted = EncryptStream(sHashing, iCipher,
 | 
			
		||||
							pbCipherKey, cbEncIV, true);
 | 
			
		||||
@@ -158,6 +170,9 @@ namespace KeePassLib.Serialization
 | 
			
		||||
					}
 | 
			
		||||
					else // KDBX >= 4
 | 
			
		||||
					{
 | 
			
		||||
						// For integrity checking (without knowing the master key)
 | 
			
		||||
						MemUtil.Write(sHashing, m_pbHashOfHeader);
 | 
			
		||||
 | 
			
		||||
						byte[] pbHeaderHmac = ComputeHeaderHmac(pbHeader, pbHmacKey64);
 | 
			
		||||
						MemUtil.Write(sHashing, pbHeaderHmac);
 | 
			
		||||
 | 
			
		||||
@@ -178,6 +193,9 @@ namespace KeePassLib.Serialization
 | 
			
		||||
						lStreams.Add(sXml);
 | 
			
		||||
					}
 | 
			
		||||
					else sXml = sPlain;
 | 
			
		||||
 | 
			
		||||
					if(m_uFileVersion >= FileVersion32_4)
 | 
			
		||||
						WriteInnerHeader(sXml); // Binary header before XML
 | 
			
		||||
				}
 | 
			
		||||
				else if(m_format == KdbxFormat.PlainXml)
 | 
			
		||||
					sXml = sHashing;
 | 
			
		||||
@@ -213,7 +231,7 @@ namespace KeePassLib.Serialization
 | 
			
		||||
#endif
 | 
			
		||||
					m_xmlWriter = xw;
 | 
			
		||||
 | 
			
		||||
					WriteDocument(pgDataSource);
 | 
			
		||||
				WriteDocument(pgRoot);
 | 
			
		||||
 | 
			
		||||
					m_xmlWriter.Flush();
 | 
			
		||||
					m_xmlWriter.Close();
 | 
			
		||||
@@ -239,6 +257,8 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			m_pbHashOfFileOnDisk = sHashing.Hash;
 | 
			
		||||
			Debug.Assert(m_pbHashOfFileOnDisk != null);
 | 
			
		||||
 | 
			
		||||
			CleanUpInnerRandomStream();
 | 
			
		||||
 | 
			
		||||
			m_xmlWriter = null;
 | 
			
		||||
			m_pbHashOfHeader = null;
 | 
			
		||||
		}
 | 
			
		||||
@@ -261,7 +281,7 @@ namespace KeePassLib.Serialization
 | 
			
		||||
 | 
			
		||||
				WriteHeaderField(ms, KdbxHeaderFieldID.MasterSeed, m_pbMasterSeed);
 | 
			
		||||
 | 
			
		||||
				if(m_uFileVersion <= FileVersion32_3)
 | 
			
		||||
				if(m_uFileVersion < FileVersion32_4)
 | 
			
		||||
				{
 | 
			
		||||
					Debug.Assert(m_pwDatabase.KdfParameters.KdfUuid.Equals(
 | 
			
		||||
						(new AesKdf()).Uuid));
 | 
			
		||||
@@ -278,15 +298,18 @@ namespace KeePassLib.Serialization
 | 
			
		||||
				if(m_pbEncryptionIV.Length > 0)
 | 
			
		||||
					WriteHeaderField(ms, KdbxHeaderFieldID.EncryptionIV, m_pbEncryptionIV);
 | 
			
		||||
 | 
			
		||||
				WriteHeaderField(ms, KdbxHeaderFieldID.ProtectedStreamKey, m_pbProtectedStreamKey);
 | 
			
		||||
				if(m_uFileVersion < FileVersion32_4)
 | 
			
		||||
				{
 | 
			
		||||
					WriteHeaderField(ms, KdbxHeaderFieldID.InnerRandomStreamKey,
 | 
			
		||||
						m_pbInnerRandomStreamKey);
 | 
			
		||||
 | 
			
		||||
				if(m_uFileVersion <= FileVersion32_3)
 | 
			
		||||
					WriteHeaderField(ms, KdbxHeaderFieldID.StreamStartBytes,
 | 
			
		||||
						m_pbStreamStartBytes);
 | 
			
		||||
 | 
			
		||||
				int nIrsID = (int)m_craInnerRandomStream;
 | 
			
		||||
				WriteHeaderField(ms, KdbxHeaderFieldID.InnerRandomStreamID,
 | 
			
		||||
					MemUtil.Int32ToBytes(nIrsID));
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// Write public custom data only when there is at least one item,
 | 
			
		||||
				// because KDBX 3.1 didn't support this field yet
 | 
			
		||||
@@ -313,7 +336,7 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			if(cb < 0) { Debug.Assert(false); throw new OutOfMemoryException(); }
 | 
			
		||||
 | 
			
		||||
			Debug.Assert(m_uFileVersion > 0);
 | 
			
		||||
			if(m_uFileVersion <= FileVersion32_3)
 | 
			
		||||
			if(m_uFileVersion < FileVersion32_4)
 | 
			
		||||
			{
 | 
			
		||||
				if(cb > (int)ushort.MaxValue)
 | 
			
		||||
				{
 | 
			
		||||
@@ -325,21 +348,64 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			}
 | 
			
		||||
			else MemUtil.Write(s, MemUtil.Int32ToBytes(cb));
 | 
			
		||||
 | 
			
		||||
			if(cb > 0) s.Write(pb, 0, cb);
 | 
			
		||||
			MemUtil.Write(s, pb);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void WriteDocument(PwGroup pgDataSource)
 | 
			
		||||
		private void WriteInnerHeader(Stream s)
 | 
			
		||||
		{
 | 
			
		||||
			int nIrsID = (int)m_craInnerRandomStream;
 | 
			
		||||
			WriteInnerHeaderField(s, KdbxInnerHeaderFieldID.InnerRandomStreamID,
 | 
			
		||||
				MemUtil.Int32ToBytes(nIrsID), null);
 | 
			
		||||
 | 
			
		||||
			WriteInnerHeaderField(s, KdbxInnerHeaderFieldID.InnerRandomStreamKey,
 | 
			
		||||
				m_pbInnerRandomStreamKey, null);
 | 
			
		||||
 | 
			
		||||
			ProtectedBinary[] vBin = m_pbsBinaries.ToArray();
 | 
			
		||||
			for(int i = 0; i < vBin.Length; ++i)
 | 
			
		||||
			{
 | 
			
		||||
				ProtectedBinary pb = vBin[i];
 | 
			
		||||
				if(pb == null) throw new InvalidOperationException();
 | 
			
		||||
 | 
			
		||||
				KdbxBinaryFlags f = KdbxBinaryFlags.None;
 | 
			
		||||
				if(pb.IsProtected) f |= KdbxBinaryFlags.Protected;
 | 
			
		||||
 | 
			
		||||
				byte[] pbFlags = new byte[1] { (byte)f };
 | 
			
		||||
				byte[] pbData = pb.ReadData();
 | 
			
		||||
 | 
			
		||||
				WriteInnerHeaderField(s, KdbxInnerHeaderFieldID.Binary,
 | 
			
		||||
					pbFlags, pbData);
 | 
			
		||||
 | 
			
		||||
				if(pb.IsProtected) MemUtil.ZeroByteArray(pbData);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			WriteInnerHeaderField(s, KdbxInnerHeaderFieldID.EndOfHeader,
 | 
			
		||||
				null, null);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void WriteInnerHeaderField(Stream s, KdbxInnerHeaderFieldID kdbID,
 | 
			
		||||
			byte[] pbData1, byte[] pbData2)
 | 
			
		||||
		{
 | 
			
		||||
			s.WriteByte((byte)kdbID);
 | 
			
		||||
 | 
			
		||||
			byte[] pb1 = (pbData1 ?? MemUtil.EmptyByteArray);
 | 
			
		||||
			byte[] pb2 = (pbData2 ?? MemUtil.EmptyByteArray);
 | 
			
		||||
 | 
			
		||||
			int cb = pb1.Length + pb2.Length;
 | 
			
		||||
			if(cb < 0) { Debug.Assert(false); throw new OutOfMemoryException(); }
 | 
			
		||||
 | 
			
		||||
			MemUtil.Write(s, MemUtil.Int32ToBytes(cb));
 | 
			
		||||
			MemUtil.Write(s, pb1);
 | 
			
		||||
			MemUtil.Write(s, pb2);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void WriteDocument(PwGroup pgRoot)
 | 
			
		||||
		{
 | 
			
		||||
			Debug.Assert(m_xmlWriter != null);
 | 
			
		||||
			if(m_xmlWriter == null) throw new InvalidOperationException();
 | 
			
		||||
 | 
			
		||||
			PwGroup pgRoot = (pgDataSource ?? m_pwDatabase.RootGroup);
 | 
			
		||||
 | 
			
		||||
			uint uNumGroups, uNumEntries, uCurEntry = 0;
 | 
			
		||||
			pgRoot.GetCounts(true, out uNumGroups, out uNumEntries);
 | 
			
		||||
 | 
			
		||||
			BinPoolBuild(pgRoot);
 | 
			
		||||
 | 
			
		||||
			m_xmlWriter.WriteStartDocument(true);
 | 
			
		||||
			m_xmlWriter.WriteStartElement(ElemDocNode);
 | 
			
		||||
 | 
			
		||||
@@ -413,11 +479,11 @@ namespace KeePassLib.Serialization
 | 
			
		||||
 | 
			
		||||
			WriteObject(ElemGenerator, PwDatabase.LocalizedAppName, false);
 | 
			
		||||
 | 
			
		||||
			if((m_pbHashOfHeader != null) && (m_uFileVersion <= FileVersion32_3))
 | 
			
		||||
			if((m_pbHashOfHeader != null) && (m_uFileVersion < FileVersion32_4))
 | 
			
		||||
				WriteObject(ElemHeaderHash, Convert.ToBase64String(
 | 
			
		||||
					m_pbHashOfHeader), false);
 | 
			
		||||
 | 
			
		||||
			if(m_uFileVersion > FileVersion32_3)
 | 
			
		||||
			if(m_uFileVersion >= FileVersion32_4)
 | 
			
		||||
				WriteObject(ElemSettingsChanged, m_pwDatabase.SettingsChanged);
 | 
			
		||||
 | 
			
		||||
			WriteObject(ElemDbName, m_pwDatabase.Name, true);
 | 
			
		||||
@@ -431,6 +497,8 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			WriteObject(ElemDbKeyChanged, m_pwDatabase.MasterKeyChanged);
 | 
			
		||||
			WriteObject(ElemDbKeyChangeRec, m_pwDatabase.MasterKeyChangeRec);
 | 
			
		||||
			WriteObject(ElemDbKeyChangeForce, m_pwDatabase.MasterKeyChangeForce);
 | 
			
		||||
			if(m_pwDatabase.MasterKeyChangeForceOnce)
 | 
			
		||||
				WriteObject(ElemDbKeyChangeForceOnce, true);
 | 
			
		||||
 | 
			
		||||
			WriteList(ElemMemoryProt, m_pwDatabase.MemoryProtection);
 | 
			
		||||
 | 
			
		||||
@@ -447,7 +515,9 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			WriteObject(ElemLastSelectedGroup, m_pwDatabase.LastSelectedGroup);
 | 
			
		||||
			WriteObject(ElemLastTopVisibleGroup, m_pwDatabase.LastTopVisibleGroup);
 | 
			
		||||
 | 
			
		||||
			if((m_format != KdbxFormat.Default) || (m_uFileVersion < FileVersion32_4))
 | 
			
		||||
			WriteBinPool();
 | 
			
		||||
 | 
			
		||||
			WriteList(ElemCustomData, m_pwDatabase.CustomData);
 | 
			
		||||
 | 
			
		||||
			m_xmlWriter.WriteEndElement();
 | 
			
		||||
@@ -715,8 +785,28 @@ namespace KeePassLib.Serialization
 | 
			
		||||
		private void WriteObject(string name, DateTime value)
 | 
			
		||||
		{
 | 
			
		||||
			Debug.Assert(name != null);
 | 
			
		||||
			Debug.Assert(value.Kind == DateTimeKind.Utc);
 | 
			
		||||
 | 
			
		||||
			WriteObject(name, TimeUtil.SerializeUtc(value), false);
 | 
			
		||||
			// Cf. ReadTime
 | 
			
		||||
			if((m_format == KdbxFormat.Default) && (m_uFileVersion >= FileVersion32_4))
 | 
			
		||||
			{
 | 
			
		||||
				DateTime dt = TimeUtil.ToUtc(value, false);
 | 
			
		||||
 | 
			
		||||
				// DateTime dtBase = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc);
 | 
			
		||||
				// dt -= new TimeSpan(dtBase.Ticks);
 | 
			
		||||
 | 
			
		||||
				// WriteObject(name, dt.ToBinary());
 | 
			
		||||
 | 
			
		||||
				// dt = TimeUtil.RoundToMultOf2PowLess1s(dt);
 | 
			
		||||
				// long lBin = dt.ToBinary();
 | 
			
		||||
 | 
			
		||||
				long lSec = dt.Ticks / TimeSpan.TicksPerSecond;
 | 
			
		||||
				// WriteObject(name, lSec);
 | 
			
		||||
 | 
			
		||||
				byte[] pb = MemUtil.Int64ToBytes(lSec);
 | 
			
		||||
				WriteObject(name, Convert.ToBase64String(pb), false);
 | 
			
		||||
		}
 | 
			
		||||
			else WriteObject(name, TimeUtil.SerializeUtc(value), false);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void WriteObject(string name, string strKeyName,
 | 
			
		||||
@@ -763,7 +853,7 @@ namespace KeePassLib.Serialization
 | 
			
		||||
					bProtected = m_pwDatabase.MemoryProtection.ProtectNotes;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if(bProtected && (m_format != KdbxFormat.PlainXml))
 | 
			
		||||
			if(bProtected && (m_format == KdbxFormat.Default))
 | 
			
		||||
			{
 | 
			
		||||
				m_xmlWriter.WriteAttributeString(AttrProtected, ValTrue);
 | 
			
		||||
 | 
			
		||||
@@ -838,11 +928,15 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			m_xmlWriter.WriteEndElement();
 | 
			
		||||
			m_xmlWriter.WriteStartElement(ElemValue);
 | 
			
		||||
 | 
			
		||||
			string strRef = (bAllowRef ? BinPoolFind(value) : null);
 | 
			
		||||
			if(strRef != null)
 | 
			
		||||
			string strRef = null;
 | 
			
		||||
			if(bAllowRef)
 | 
			
		||||
			{
 | 
			
		||||
				m_xmlWriter.WriteAttributeString(AttrRef, strRef);
 | 
			
		||||
				int iRef = m_pbsBinaries.Find(value);
 | 
			
		||||
				if(iRef >= 0) strRef = iRef.ToString(NumberFormatInfo.InvariantInfo);
 | 
			
		||||
				else { Debug.Assert(false); }
 | 
			
		||||
			}
 | 
			
		||||
			if(strRef != null)
 | 
			
		||||
				m_xmlWriter.WriteAttributeString(AttrRef, strRef);
 | 
			
		||||
			else SubWriteValue(value);
 | 
			
		||||
 | 
			
		||||
			m_xmlWriter.WriteEndElement(); // ElemValue
 | 
			
		||||
@@ -851,7 +945,7 @@ namespace KeePassLib.Serialization
 | 
			
		||||
 | 
			
		||||
		private void SubWriteValue(ProtectedBinary value)
 | 
			
		||||
		{
 | 
			
		||||
			if(value.IsProtected && (m_format != KdbxFormat.PlainXml))
 | 
			
		||||
			if(value.IsProtected && (m_format == KdbxFormat.Default))
 | 
			
		||||
			{
 | 
			
		||||
				m_xmlWriter.WriteAttributeString(AttrProtected, ValTrue);
 | 
			
		||||
 | 
			
		||||
@@ -861,18 +955,26 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				if(m_pwDatabase.Compression == PwCompressionAlgorithm.GZip)
 | 
			
		||||
				if(m_pwDatabase.Compression != PwCompressionAlgorithm.None)
 | 
			
		||||
				{
 | 
			
		||||
					m_xmlWriter.WriteAttributeString(AttrCompressed, ValTrue);
 | 
			
		||||
 | 
			
		||||
					byte[] pbRaw = value.ReadData();
 | 
			
		||||
					byte[] pbCmp = MemUtil.Compress(pbRaw);
 | 
			
		||||
					m_xmlWriter.WriteBase64(pbCmp, 0, pbCmp.Length);
 | 
			
		||||
 | 
			
		||||
					if(value.IsProtected)
 | 
			
		||||
					{
 | 
			
		||||
						MemUtil.ZeroByteArray(pbRaw);
 | 
			
		||||
						MemUtil.ZeroByteArray(pbCmp);
 | 
			
		||||
				}
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					byte[] pbRaw = value.ReadData();
 | 
			
		||||
					m_xmlWriter.WriteBase64(pbRaw, 0, pbRaw.Length);
 | 
			
		||||
 | 
			
		||||
					if(value.IsProtected) MemUtil.ZeroByteArray(pbRaw);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@@ -892,11 +994,13 @@ namespace KeePassLib.Serialization
 | 
			
		||||
		{
 | 
			
		||||
			m_xmlWriter.WriteStartElement(ElemBinaries);
 | 
			
		||||
 | 
			
		||||
			foreach(KeyValuePair<string, ProtectedBinary> kvp in m_dictBinPool)
 | 
			
		||||
			ProtectedBinary[] v = m_pbsBinaries.ToArray();
 | 
			
		||||
			for(int i = 0; i < v.Length; ++i)
 | 
			
		||||
			{
 | 
			
		||||
				m_xmlWriter.WriteStartElement(ElemBinary);
 | 
			
		||||
				m_xmlWriter.WriteAttributeString(AttrId, kvp.Key);
 | 
			
		||||
				SubWriteValue(kvp.Value);
 | 
			
		||||
				m_xmlWriter.WriteAttributeString(AttrId,
 | 
			
		||||
					i.ToString(NumberFormatInfo.InvariantInfo));
 | 
			
		||||
				SubWriteValue(v[i]);
 | 
			
		||||
				m_xmlWriter.WriteEndElement();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@@ -904,21 +1008,23 @@ namespace KeePassLib.Serialization
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		[Obsolete]
 | 
			
		||||
		public static bool WriteEntries(Stream msOutput, PwDatabase pwDatabase,
 | 
			
		||||
			PwEntry[] vEntries)
 | 
			
		||||
		public static bool WriteEntries(Stream msOutput, PwEntry[] vEntries)
 | 
			
		||||
		{
 | 
			
		||||
			return WriteEntries(msOutput, vEntries);
 | 
			
		||||
			return WriteEntries(msOutput, null, vEntries);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static bool WriteEntries(Stream msOutput, PwDatabase pdContext,
 | 
			
		||||
			PwEntry[] vEntries)
 | 
			
		||||
		{
 | 
			
		||||
			if(msOutput == null) { Debug.Assert(false); return false; }
 | 
			
		||||
		/// <summary>
 | 
			
		||||
			if(vEntries == null) { Debug.Assert(false); return false; }
 | 
			
		||||
		/// Write entries to a stream.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		/// <param name="msOutput">Output stream to which the entries will be written.</param>
 | 
			
		||||
		/// <param name="vEntries">Entries to serialize.</param>
 | 
			
		||||
		/// <returns>Returns <c>true</c>, if the entries were written successfully
 | 
			
		||||
		/// to the stream.</returns>
 | 
			
		||||
		public static bool WriteEntries(Stream msOutput, PwEntry[] vEntries)
 | 
			
		||||
		{
 | 
			
		||||
			/* KdbxFile f = new KdbxFile(pwDatabase);
 | 
			
		||||
			f.m_format = KdbxFormat.PlainXml;
 | 
			
		||||
 | 
			
		||||
@@ -941,17 +1047,31 @@ namespace KeePassLib.Serialization
 | 
			
		||||
 | 
			
		||||
			xtw.WriteEndElement();
 | 
			
		||||
			xtw.WriteEndDocument();
 | 
			
		||||
 | 
			
		||||
			xtw.Flush();
 | 
			
		||||
			xtw.Close();
 | 
			
		||||
			return true; */
 | 
			
		||||
 | 
			
		||||
			PwDatabase pd = new PwDatabase();
 | 
			
		||||
			pd.New(new IOConnectionInfo(), new CompositeKey());
 | 
			
		||||
 | 
			
		||||
			foreach(PwEntry peCopy in vEntries)
 | 
			
		||||
				pd.RootGroup.AddEntry(peCopy.CloneDeep(), true);
 | 
			
		||||
 | 
			
		||||
			PwGroup pg = pd.RootGroup;
 | 
			
		||||
			if(pg == null) { Debug.Assert(false); return false; }
 | 
			
		||||
			xtw.Flush();
 | 
			
		||||
			foreach(PwEntry pe in vEntries)
 | 
			
		||||
			{
 | 
			
		||||
				PwUuid pu = pe.CustomIconUuid;
 | 
			
		||||
				if(!pu.Equals(PwUuid.Zero) && (pd.GetCustomIconIndex(pu) < 0))
 | 
			
		||||
				{
 | 
			
		||||
					int i = -1;
 | 
			
		||||
					if(pdContext != null) i = pdContext.GetCustomIconIndex(pu);
 | 
			
		||||
					if(i >= 0)
 | 
			
		||||
					{
 | 
			
		||||
						PwCustomIcon ci = pdContext.CustomIcons[i];
 | 
			
		||||
						pd.CustomIcons.Add(ci);
 | 
			
		||||
					}
 | 
			
		||||
					else { Debug.Assert(pdContext == null); }
 | 
			
		||||
				}
 | 
			
		||||
			xtw.Close();
 | 
			
		||||
				PwEntry peCopy = pe.CloneDeep();
 | 
			
		||||
				pg.AddEntry(peCopy, true);
 | 
			
		||||
			}
 | 
			
		||||
			return true; */
 | 
			
		||||
			KdbxFile f = new KdbxFile(pd);
 | 
			
		||||
			f.Save(msOutput, null, KdbxFormat.PlainXml, null);
 | 
			
		||||
			return true;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -125,7 +125,9 @@ namespace KeePassLib.Serialization
 | 
			
		||||
		/// file version is too high), the last 2 bytes are informational.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		private const uint FileVersion32 = 0x00040000;
 | 
			
		||||
		private const uint FileVersion32_3 = 0x00030001; // Old format
 | 
			
		||||
 | 
			
		||||
		internal const uint FileVersion32_4 = 0x00040000; // First of 4.x series
 | 
			
		||||
		internal const uint FileVersion32_3 = 0x00030001; // Old format 3.1
 | 
			
		||||
 | 
			
		||||
		private const uint FileVersionCriticalMask = 0xFFFF0000;
 | 
			
		||||
 | 
			
		||||
@@ -156,6 +158,7 @@ namespace KeePassLib.Serialization
 | 
			
		||||
		private const string ElemDbKeyChanged = "MasterKeyChanged";
 | 
			
		||||
		private const string ElemDbKeyChangeRec = "MasterKeyChangeRec";
 | 
			
		||||
		private const string ElemDbKeyChangeForce = "MasterKeyChangeForce";
 | 
			
		||||
		private const string ElemDbKeyChangeForceOnce = "MasterKeyChangeForceOnce";
 | 
			
		||||
		private const string ElemRecycleBinEnabled = "RecycleBinEnabled";
 | 
			
		||||
		private const string ElemRecycleBinUuid = "RecycleBinUUID";
 | 
			
		||||
		private const string ElemRecycleBinChanged = "RecycleBinChanged";
 | 
			
		||||
@@ -239,6 +242,7 @@ namespace KeePassLib.Serialization
 | 
			
		||||
		private const string ElemStringDictExItem = "Item";
 | 
			
		||||
 | 
			
		||||
		private PwDatabase m_pwDatabase; // Not null, see constructor
 | 
			
		||||
		private bool m_bUsedOnce = false;
 | 
			
		||||
 | 
			
		||||
		private XmlWriter m_xmlWriter = null;
 | 
			
		||||
		private CryptoRandomStream m_randomStream = null;
 | 
			
		||||
@@ -249,20 +253,19 @@ namespace KeePassLib.Serialization
 | 
			
		||||
		private byte[] m_pbMasterSeed = null;
 | 
			
		||||
		// private byte[] m_pbTransformSeed = null;
 | 
			
		||||
		private byte[] m_pbEncryptionIV = null;
 | 
			
		||||
		private byte[] m_pbProtectedStreamKey = null;
 | 
			
		||||
		private byte[] m_pbStreamStartBytes = null;
 | 
			
		||||
 | 
			
		||||
		// ArcFourVariant only for backward compatibility; KeePass defaults
 | 
			
		||||
		// to a more secure algorithm when *writing* databases
 | 
			
		||||
		private CrsAlgorithm m_craInnerRandomStream = CrsAlgorithm.ArcFourVariant;
 | 
			
		||||
		private byte[] m_pbInnerRandomStreamKey = null;
 | 
			
		||||
 | 
			
		||||
		private Dictionary<string, ProtectedBinary> m_dictBinPool =
 | 
			
		||||
			new Dictionary<string, ProtectedBinary>();
 | 
			
		||||
		private ProtectedBinarySet m_pbsBinaries = new ProtectedBinarySet();
 | 
			
		||||
 | 
			
		||||
		private byte[] m_pbHashOfHeader = null;
 | 
			
		||||
		private byte[] m_pbHashOfFileOnDisk = null;
 | 
			
		||||
 | 
			
		||||
		private readonly DateTime m_dtNow = DateTime.Now; // Cache current time
 | 
			
		||||
		private readonly DateTime m_dtNow = DateTime.UtcNow; // Cache current time
 | 
			
		||||
 | 
			
		||||
		private const uint NeutralLanguageOffset = 0x100000; // 2^20, see 32-bit Unicode specs
 | 
			
		||||
		private const uint NeutralLanguageIDSec = 0x7DC5C; // See 32-bit Unicode specs
 | 
			
		||||
@@ -279,13 +282,29 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			TransformSeed = 5, // KDBX 3.1, for backward compatibility only
 | 
			
		||||
			TransformRounds = 6, // KDBX 3.1, for backward compatibility only
 | 
			
		||||
			EncryptionIV = 7,
 | 
			
		||||
			ProtectedStreamKey = 8,
 | 
			
		||||
			InnerRandomStreamKey = 8, // KDBX 3.1, for backward compatibility only
 | 
			
		||||
			StreamStartBytes = 9, // KDBX 3.1, for backward compatibility only
 | 
			
		||||
			InnerRandomStreamID = 10,
 | 
			
		||||
			KdfParameters = 11, // KDBX 4
 | 
			
		||||
			InnerRandomStreamID = 10, // KDBX 3.1, for backward compatibility only
 | 
			
		||||
			KdfParameters = 11, // KDBX 4, superseding Transform*
 | 
			
		||||
			PublicCustomData = 12 // KDBX 4
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Inner header in KDBX >= 4 files
 | 
			
		||||
		private enum KdbxInnerHeaderFieldID : byte
 | 
			
		||||
		{
 | 
			
		||||
			EndOfHeader = 0,
 | 
			
		||||
			InnerRandomStreamID = 1, // Supersedes KdbxHeaderFieldID.InnerRandomStreamID
 | 
			
		||||
			InnerRandomStreamKey = 2, // Supersedes KdbxHeaderFieldID.InnerRandomStreamKey
 | 
			
		||||
			Binary = 3
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		[Flags]
 | 
			
		||||
		private enum KdbxBinaryFlags : byte
 | 
			
		||||
		{
 | 
			
		||||
			None = 0,
 | 
			
		||||
			Protected = 1
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public byte[] HashOfFileOnDisk
 | 
			
		||||
		{
 | 
			
		||||
			get { return m_pbHashOfFileOnDisk; }
 | 
			
		||||
@@ -298,6 +317,13 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			set { m_bRepairMode = value; }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private uint m_uForceVersion = 0;
 | 
			
		||||
		internal uint ForceVersion
 | 
			
		||||
		{
 | 
			
		||||
			get { return m_uForceVersion; }
 | 
			
		||||
			set { m_uForceVersion = value; }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private string m_strDetachBins = null;
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Detach binaries when opening a file. If this isn't <c>null</c>,
 | 
			
		||||
@@ -344,6 +370,10 @@ namespace KeePassLib.Serialization
 | 
			
		||||
 | 
			
		||||
		private uint GetMinKdbxVersion()
 | 
			
		||||
		{
 | 
			
		||||
			if(m_uForceVersion != 0) return m_uForceVersion;
 | 
			
		||||
 | 
			
		||||
			// See also KeePassKdb2x3.Export (KDBX 3.1 export module)
 | 
			
		||||
 | 
			
		||||
			AesKdf kdfAes = new AesKdf();
 | 
			
		||||
			if(!kdfAes.Uuid.Equals(m_pwDatabase.KdfParameters.KdfUuid))
 | 
			
		||||
				return FileVersion32;
 | 
			
		||||
@@ -488,64 +518,12 @@ namespace KeePassLib.Serialization
 | 
			
		||||
			// Do not clear the list
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void BinPoolBuild(PwGroup pgDataSource)
 | 
			
		||||
		private void CleanUpInnerRandomStream()
 | 
			
		||||
		{
 | 
			
		||||
			m_dictBinPool = new Dictionary<string, ProtectedBinary>();
 | 
			
		||||
			if(m_randomStream != null) m_randomStream.Dispose();
 | 
			
		||||
 | 
			
		||||
			if(pgDataSource == null) { Debug.Assert(false); return; }
 | 
			
		||||
 | 
			
		||||
			EntryHandler eh = delegate(PwEntry pe)
 | 
			
		||||
			{
 | 
			
		||||
				foreach(PwEntry peHistory in pe.History)
 | 
			
		||||
				{
 | 
			
		||||
					BinPoolAdd(peHistory.Binaries);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				BinPoolAdd(pe.Binaries);
 | 
			
		||||
				return true;
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			pgDataSource.TraverseTree(TraversalMethod.PreOrder, null, eh);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void BinPoolAdd(ProtectedBinaryDictionary dict)
 | 
			
		||||
		{
 | 
			
		||||
			foreach(KeyValuePair<string, ProtectedBinary> kvp in dict)
 | 
			
		||||
			{
 | 
			
		||||
				BinPoolAdd(kvp.Value);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void BinPoolAdd(ProtectedBinary pb)
 | 
			
		||||
		{
 | 
			
		||||
			if(pb == null) { Debug.Assert(false); return; }
 | 
			
		||||
 | 
			
		||||
			if(BinPoolFind(pb) != null) return; // Exists already
 | 
			
		||||
 | 
			
		||||
			m_dictBinPool.Add(m_dictBinPool.Count.ToString(
 | 
			
		||||
				NumberFormatInfo.InvariantInfo), pb);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private string BinPoolFind(ProtectedBinary pb)
 | 
			
		||||
		{
 | 
			
		||||
			if(pb == null) { Debug.Assert(false); return null; }
 | 
			
		||||
 | 
			
		||||
			foreach(KeyValuePair<string, ProtectedBinary> kvp in m_dictBinPool)
 | 
			
		||||
			{
 | 
			
		||||
				if(pb.Equals(kvp.Value)) return kvp.Key;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private ProtectedBinary BinPoolGet(string strKey)
 | 
			
		||||
		{
 | 
			
		||||
			if(strKey == null) { Debug.Assert(false); return null; }
 | 
			
		||||
 | 
			
		||||
			ProtectedBinary pb;
 | 
			
		||||
			if(m_dictBinPool.TryGetValue(strKey, out pb)) return pb;
 | 
			
		||||
 | 
			
		||||
			return null;
 | 
			
		||||
			if(m_pbInnerRandomStreamKey != null)
 | 
			
		||||
				MemUtil.ZeroByteArray(m_pbInnerRandomStreamKey);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static void SaveBinary(string strName, ProtectedBinary pb,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  
 | 
			
		||||
  Modified to be used with Mono for Android. Changes Copyright (C) 2013 Philipp Crocoll
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  
 | 
			
		||||
  Modified to be used with Mono for Android. Changes Copyright (C) 2013 Philipp Crocoll
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -21,15 +19,16 @@
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Xml.Serialization;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
 | 
			
		||||
#if !KeePassUAP
 | 
			
		||||
using System.Windows.Forms;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace KeePassLib.Translation
 | 
			
		||||
{
 | 
			
		||||
	public class Form
 | 
			
		||||
	{}
 | 
			
		||||
	public sealed class KPFormCustomization
 | 
			
		||||
	{
 | 
			
		||||
		private string m_strFQName = string.Empty;
 | 
			
		||||
@@ -69,7 +68,7 @@ namespace KeePassLib.Translation
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
#if (!KeePassLibSD && !KeePassRT)
 | 
			
		||||
#if (!KeePassLibSD && !KeePassUAP)
 | 
			
		||||
		private Form m_formEnglish = null;
 | 
			
		||||
		[XmlIgnore]
 | 
			
		||||
		public Form FormEnglish
 | 
			
		||||
@@ -78,7 +77,7 @@ namespace KeePassLib.Translation
 | 
			
		||||
			set { m_formEnglish = value; }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/*public void ApplyTo(Form form)
 | 
			
		||||
		public void ApplyTo(Form form)
 | 
			
		||||
		{
 | 
			
		||||
			Debug.Assert(form != null); if(form == null) throw new ArgumentNullException("form");
 | 
			
		||||
			
 | 
			
		||||
@@ -103,7 +102,7 @@ namespace KeePassLib.Translation
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			foreach(Control cSub in c.Controls) ApplyToControl(cSub);
 | 
			
		||||
		}*/
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -57,7 +57,7 @@ namespace KeePassLib.Utility
 | 
			
		||||
				string strPath = strTemp + strPrefix + "-";
 | 
			
		||||
				Debug.Assert(strPath.IndexOf('/') < 0);
 | 
			
		||||
 | 
			
		||||
				DateTime dtNow = DateTime.Now;
 | 
			
		||||
				DateTime dtNow = DateTime.UtcNow;
 | 
			
		||||
				string strTime = dtNow.ToString("s");
 | 
			
		||||
				strTime = strTime.Replace('T', '-');
 | 
			
		||||
				strTime = strTime.Replace(':', '-');
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  
 | 
			
		||||
  Modified to be used with Mono for Android. Changes Copyright (C) 2013 Philipp Crocoll
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -22,45 +20,29 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Collections.Specialized;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
#if !KeePassUAP
 | 
			
		||||
using System.Windows.Forms;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
using KeePassLib.Resources;
 | 
			
		||||
using KeePassLib.Serialization;
 | 
			
		||||
 | 
			
		||||
namespace KeePassLib.Utility
 | 
			
		||||
{
 | 
			
		||||
	public enum MessageBoxButtons
 | 
			
		||||
	{
 | 
			
		||||
		OK, OKCancel, AbortRetryIgnore, YesNoCancel, YesNo, RetryCancel
 | 
			
		||||
	}
 | 
			
		||||
	public enum MessageBoxIcon
 | 
			
		||||
	{
 | 
			
		||||
		Information, Warning, Error, Question
 | 
			
		||||
	}
 | 
			
		||||
	public enum MessageBoxDefaultButton
 | 
			
		||||
	{
 | 
			
		||||
		Button1, Button2, Button3
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public enum DialogResult
 | 
			
		||||
	{
 | 
			
		||||
		Yes, No, Cancel, Retry, Abort
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	public sealed class MessageServiceEventArgs : EventArgs
 | 
			
		||||
	{
 | 
			
		||||
		private string m_strTitle = string.Empty;
 | 
			
		||||
		private string m_strText = string.Empty;
 | 
			
		||||
		//private MessageBoxButtons m_msgButtons = MessageBoxButtons.OK;
 | 
			
		||||
		//private MessageBoxIcon m_msgIcon = MessageBoxIcon.None;
 | 
			
		||||
		private MessageBoxButtons m_msgButtons = MessageBoxButtons.OK;
 | 
			
		||||
		private MessageBoxIcon m_msgIcon = MessageBoxIcon.None;
 | 
			
		||||
 | 
			
		||||
		public string Title { get { return m_strTitle; } }
 | 
			
		||||
		public string Text { get { return m_strText; } }
 | 
			
		||||
		//public MessageBoxButtons Buttons { get { return m_msgButtons; } }
 | 
			
		||||
		//public MessageBoxIcon Icon { get { return m_msgIcon; } }
 | 
			
		||||
		public MessageBoxButtons Buttons { get { return m_msgButtons; } }
 | 
			
		||||
		public MessageBoxIcon Icon { get { return m_msgIcon; } }
 | 
			
		||||
 | 
			
		||||
		public MessageServiceEventArgs() { }
 | 
			
		||||
 | 
			
		||||
@@ -69,7 +51,8 @@ namespace KeePassLib.Utility
 | 
			
		||||
		{
 | 
			
		||||
			m_strTitle = (strTitle ?? string.Empty);
 | 
			
		||||
			m_strText = (strText ?? string.Empty);
 | 
			
		||||
 | 
			
		||||
			m_msgButtons = msgButtons;
 | 
			
		||||
			m_msgIcon = msgIcon;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -82,12 +65,14 @@ namespace KeePassLib.Utility
 | 
			
		||||
		private const MessageBoxIcon m_mbiWarning = MessageBoxIcon.Warning;
 | 
			
		||||
		private const MessageBoxIcon m_mbiFatal = MessageBoxIcon.Error;
 | 
			
		||||
 | 
			
		||||
		private const MessageBoxOptions m_mboRtl = (MessageBoxOptions.RtlReading |
 | 
			
		||||
			MessageBoxOptions.RightAlign);
 | 
			
		||||
#else
 | 
			
		||||
		private const MessageBoxIcon m_mbiInfo = MessageBoxIcon.Asterisk;
 | 
			
		||||
		private const MessageBoxIcon m_mbiWarning = MessageBoxIcon.Exclamation;
 | 
			
		||||
		private const MessageBoxIcon m_mbiFatal = MessageBoxIcon.Hand;
 | 
			
		||||
#endif
 | 
			
		||||
		//private const MessageBoxIcon m_mbiQuestion = MessageBoxIcon.Question;
 | 
			
		||||
		private const MessageBoxIcon m_mbiQuestion = MessageBoxIcon.Question;
 | 
			
		||||
 | 
			
		||||
		public static string NewLine
 | 
			
		||||
		{
 | 
			
		||||
@@ -112,7 +97,9 @@ namespace KeePassLib.Utility
 | 
			
		||||
			get { return m_uCurrentMessageCount; }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
#if !KeePassUAP
 | 
			
		||||
		public static event EventHandler<MessageServiceEventArgs> MessageShowing;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		private static string ObjectsToMessage(object[] vLines)
 | 
			
		||||
		{
 | 
			
		||||
@@ -136,7 +123,7 @@ namespace KeePassLib.Utility
 | 
			
		||||
 | 
			
		||||
				Exception exObj = (obj as Exception);
 | 
			
		||||
				string strObj = (obj as string);
 | 
			
		||||
#if (!KeePassLibSD && !KeePassRT)
 | 
			
		||||
#if !KeePassLibSD
 | 
			
		||||
				StringCollection scObj = (obj as StringCollection);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -147,7 +134,7 @@ namespace KeePassLib.Utility
 | 
			
		||||
					else if((exObj.Message != null) && (exObj.Message.Length > 0))
 | 
			
		||||
						strAppend = exObj.Message;
 | 
			
		||||
				}
 | 
			
		||||
#if (!KeePassLibSD && !KeePassRT)
 | 
			
		||||
#if !KeePassLibSD
 | 
			
		||||
				else if(scObj != null)
 | 
			
		||||
				{
 | 
			
		||||
					StringBuilder sb = new StringBuilder();
 | 
			
		||||
@@ -176,30 +163,24 @@ namespace KeePassLib.Utility
 | 
			
		||||
			return sbText.ToString();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
#if (!KeePassLibSD && !KeePassRT)
 | 
			
		||||
		/*internal static Form GetTopForm()
 | 
			
		||||
#if (!KeePassLibSD && !KeePassUAP)
 | 
			
		||||
		internal static Form GetTopForm()
 | 
			
		||||
		{
 | 
			
		||||
			FormCollection fc = Application.OpenForms;
 | 
			
		||||
			if((fc == null) || (fc.Count == 0)) return null;
 | 
			
		||||
 | 
			
		||||
			return fc[fc.Count - 1];
 | 
			
		||||
		}*/
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		private static DialogResult SafeShowMessageBox(string strText, string strTitle,
 | 
			
		||||
#if !KeePassUAP
 | 
			
		||||
		internal static DialogResult SafeShowMessageBox(string strText, string strTitle,
 | 
			
		||||
			MessageBoxButtons mb, MessageBoxIcon mi, MessageBoxDefaultButton mdb)
 | 
			
		||||
		{
 | 
			
		||||
#if (KeePassLibSD || KeePassRT)
 | 
			
		||||
#if KeePassLibSD
 | 
			
		||||
			return MessageBox.Show(strText, strTitle, mb, mi, mdb);
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
			if (mb == MessageBoxButtons.OK)
 | 
			
		||||
			{
 | 
			
		||||
				//Android.Widget.Toast toast = ..
 | 
			
		||||
			}
 | 
			
		||||
			//this might help: http://www.gregshackles.com/2011/04/using-background-threads-in-mono-for-android-applications/
 | 
			
		||||
			throw new NotImplementedException();
 | 
			
		||||
			/*IWin32Window wnd = null;
 | 
			
		||||
			IWin32Window wnd = null;
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
				Form f = GetTopForm();
 | 
			
		||||
@@ -228,12 +209,11 @@ namespace KeePassLib.Utility
 | 
			
		||||
			if(StrUtil.RightToLeft)
 | 
			
		||||
				return MessageBox.Show(strText, strTitle, mb, mi, mdb, m_mboRtl);
 | 
			
		||||
			return MessageBox.Show(strText, strTitle, mb, mi, mdb);
 | 
			
		||||
			*/
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
#if (!KeePassLibSD && !KeePassRT)
 | 
			
		||||
	/*	internal delegate DialogResult SafeShowMessageBoxInternalDelegate(IWin32Window iParent,
 | 
			
		||||
#if !KeePassLibSD
 | 
			
		||||
		internal delegate DialogResult SafeShowMessageBoxInternalDelegate(IWin32Window iParent,
 | 
			
		||||
			string strText, string strTitle, MessageBoxButtons mb, MessageBoxIcon mi,
 | 
			
		||||
			MessageBoxDefaultButton mdb);
 | 
			
		||||
 | 
			
		||||
@@ -244,7 +224,7 @@ namespace KeePassLib.Utility
 | 
			
		||||
			if(StrUtil.RightToLeft)
 | 
			
		||||
				return MessageBox.Show(iParent, strText, strTitle, mb, mi, mdb, m_mboRtl);
 | 
			
		||||
			return MessageBox.Show(iParent, strText, strTitle, mb, mi, mdb);
 | 
			
		||||
		}*/
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		public static void ShowInfo(params object[] vLines)
 | 
			
		||||
@@ -309,12 +289,13 @@ namespace KeePassLib.Utility
 | 
			
		||||
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
#if !KeePassLibSD
 | 
			
		||||
				/* nicht benoetigt - hoffentlich :-)
 | 
			
		||||
Clipboard.Clear();
 | 
			
		||||
Clipboard.SetText(ObjectsToMessage(vLines, true));*/
 | 
			
		||||
				string strDetails = ObjectsToMessage(vLines, true);
 | 
			
		||||
 | 
			
		||||
#if KeePassLibSD
 | 
			
		||||
				Clipboard.SetDataObject(strDetails);
 | 
			
		||||
#else
 | 
			
		||||
				Clipboard.SetDataObject(ObjectsToMessage(vLines, true));
 | 
			
		||||
				Clipboard.Clear();
 | 
			
		||||
				Clipboard.SetText(strDetails);
 | 
			
		||||
#endif
 | 
			
		||||
			}
 | 
			
		||||
			catch(Exception) { Debug.Assert(false); }
 | 
			
		||||
@@ -339,10 +320,10 @@ Clipboard.SetText(ObjectsToMessage(vLines, true));*/
 | 
			
		||||
 | 
			
		||||
			if(MessageService.MessageShowing != null)
 | 
			
		||||
				MessageService.MessageShowing(null, new MessageServiceEventArgs(
 | 
			
		||||
					strTitleEx, strTextEx, mbb, MessageBoxIcon.Question));
 | 
			
		||||
					strTitleEx, strTextEx, mbb, m_mbiQuestion));
 | 
			
		||||
 | 
			
		||||
			DialogResult dr = SafeShowMessageBox(strTextEx, strTitleEx, mbb,
 | 
			
		||||
			                                     MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
 | 
			
		||||
				m_mbiQuestion, MessageBoxDefaultButton.Button1);
 | 
			
		||||
 | 
			
		||||
			--m_uCurrentMessageCount;
 | 
			
		||||
			return dr;
 | 
			
		||||
@@ -358,10 +339,10 @@ Clipboard.SetText(ObjectsToMessage(vLines, true));*/
 | 
			
		||||
 | 
			
		||||
			if(MessageService.MessageShowing != null)
 | 
			
		||||
				MessageService.MessageShowing(null, new MessageServiceEventArgs(
 | 
			
		||||
					strTitleEx, strTextEx, MessageBoxButtons.YesNo, MessageBoxIcon.Question));
 | 
			
		||||
					strTitleEx, strTextEx, MessageBoxButtons.YesNo, mbi));
 | 
			
		||||
 | 
			
		||||
			DialogResult dr = SafeShowMessageBox(strTextEx, strTitleEx,
 | 
			
		||||
			                                     MessageBoxButtons.YesNo, MessageBoxIcon.Question, bDefaultToYes ?
 | 
			
		||||
				MessageBoxButtons.YesNo, mbi, bDefaultToYes ?
 | 
			
		||||
				MessageBoxDefaultButton.Button1 : MessageBoxDefaultButton.Button2);
 | 
			
		||||
 | 
			
		||||
			--m_uCurrentMessageCount;
 | 
			
		||||
@@ -370,17 +351,17 @@ Clipboard.SetText(ObjectsToMessage(vLines, true));*/
 | 
			
		||||
 | 
			
		||||
		public static bool AskYesNo(string strText, string strTitle, bool bDefaultToYes)
 | 
			
		||||
		{
 | 
			
		||||
			return AskYesNo(strText, strTitle, bDefaultToYes, MessageBoxIcon.Question);
 | 
			
		||||
			return AskYesNo(strText, strTitle, bDefaultToYes, m_mbiQuestion);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static bool AskYesNo(string strText, string strTitle)
 | 
			
		||||
		{
 | 
			
		||||
			return AskYesNo(strText, strTitle, true, MessageBoxIcon.Question);
 | 
			
		||||
			return AskYesNo(strText, strTitle, true, m_mbiQuestion);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static bool AskYesNo(string strText)
 | 
			
		||||
		{
 | 
			
		||||
			return AskYesNo(strText, null, true, MessageBoxIcon.Question);
 | 
			
		||||
			return AskYesNo(strText, null, true, m_mbiQuestion);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static void ShowLoadWarning(string strFilePath, Exception ex)
 | 
			
		||||
@@ -391,21 +372,7 @@ Clipboard.SetText(ObjectsToMessage(vLines, true));*/
 | 
			
		||||
		public static void ShowLoadWarning(string strFilePath, Exception ex,
 | 
			
		||||
			bool bFullException)
 | 
			
		||||
		{
 | 
			
		||||
			string str = string.Empty;
 | 
			
		||||
 | 
			
		||||
			if((strFilePath != null) && (strFilePath.Length > 0))
 | 
			
		||||
				str += strFilePath + MessageService.NewParagraph;
 | 
			
		||||
 | 
			
		||||
			str += KLRes.FileLoadFailed;
 | 
			
		||||
 | 
			
		||||
			if((ex != null) && (ex.Message != null) && (ex.Message.Length > 0))
 | 
			
		||||
			{
 | 
			
		||||
				str += MessageService.NewParagraph;
 | 
			
		||||
				if(!bFullException) str += ex.Message;
 | 
			
		||||
				else str += ObjectsToMessage(new object[] { ex }, true);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			ShowWarning(str);
 | 
			
		||||
			ShowWarning(GetLoadWarningMessage(strFilePath, ex, bFullException));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static void ShowLoadWarning(IOConnectionInfo ioConnection, Exception ex)
 | 
			
		||||
@@ -425,18 +392,7 @@ Clipboard.SetText(ObjectsToMessage(vLines, true));*/
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			string str = string.Empty;
 | 
			
		||||
			if((strFilePath != null) && (strFilePath.Length > 0))
 | 
			
		||||
				str += strFilePath + MessageService.NewParagraph;
 | 
			
		||||
 | 
			
		||||
			str += KLRes.FileSaveFailed;
 | 
			
		||||
 | 
			
		||||
			if((ex != null) && (ex.Message != null) && (ex.Message.Length > 0))
 | 
			
		||||
				str += MessageService.NewParagraph + ex.Message;
 | 
			
		||||
 | 
			
		||||
			if(bCorruptionWarning)
 | 
			
		||||
				str += MessageService.NewParagraph + KLRes.FileSaveCorruptionWarning;
 | 
			
		||||
 | 
			
		||||
			string str = GetSaveWarningMessage(strFilePath, ex, bCorruptionWarning);
 | 
			
		||||
			ShowWarning(str);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -447,6 +403,45 @@ Clipboard.SetText(ObjectsToMessage(vLines, true));*/
 | 
			
		||||
				ShowSaveWarning(ioConnection.GetDisplayName(), ex, bCorruptionWarning);
 | 
			
		||||
			else ShowWarning(ex);
 | 
			
		||||
		}
 | 
			
		||||
#endif // !KeePassUAP
 | 
			
		||||
 | 
			
		||||
		internal static string GetLoadWarningMessage(string strFilePath,
 | 
			
		||||
			Exception ex, bool bFullException)
 | 
			
		||||
		{
 | 
			
		||||
			string str = string.Empty;
 | 
			
		||||
 | 
			
		||||
			if(!string.IsNullOrEmpty(strFilePath))
 | 
			
		||||
				str += strFilePath + MessageService.NewParagraph;
 | 
			
		||||
 | 
			
		||||
			str += KLRes.FileLoadFailed;
 | 
			
		||||
 | 
			
		||||
			if((ex != null) && !string.IsNullOrEmpty(ex.Message))
 | 
			
		||||
			{
 | 
			
		||||
				str += MessageService.NewParagraph;
 | 
			
		||||
				if(!bFullException) str += ex.Message;
 | 
			
		||||
				else str += ObjectsToMessage(new object[] { ex }, true);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return str;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		internal static string GetSaveWarningMessage(string strFilePath,
 | 
			
		||||
			Exception ex, bool bCorruptionWarning)
 | 
			
		||||
		{
 | 
			
		||||
			string str = string.Empty;
 | 
			
		||||
			if(!string.IsNullOrEmpty(strFilePath))
 | 
			
		||||
				str += strFilePath + MessageService.NewParagraph;
 | 
			
		||||
 | 
			
		||||
			str += KLRes.FileSaveFailed;
 | 
			
		||||
 | 
			
		||||
			if((ex != null) && !string.IsNullOrEmpty(ex.Message))
 | 
			
		||||
				str += MessageService.NewParagraph + ex.Message;
 | 
			
		||||
 | 
			
		||||
			if(bCorruptionWarning)
 | 
			
		||||
				str += MessageService.NewParagraph + KLRes.FileSaveCorruptionWarning;
 | 
			
		||||
 | 
			
		||||
			return str;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static void ExternalIncrementMessageCount()
 | 
			
		||||
		{
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@ using System.Diagnostics;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Xml;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -34,6 +35,8 @@ namespace KeePassLib.Utility
 | 
			
		||||
	public static class MonoWorkarounds
 | 
			
		||||
	{
 | 
			
		||||
		private static Dictionary<uint, bool> m_dForceReq = new Dictionary<uint, bool>();
 | 
			
		||||
		private static Thread m_thFixClip = null;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		private static bool? m_bReq = null;
 | 
			
		||||
		public static bool IsRequired()
 | 
			
		||||
@@ -114,6 +117,17 @@ namespace KeePassLib.Utility
 | 
			
		||||
		// 3574233558:
 | 
			
		||||
		//   Problems with minimizing windows, no content rendered.
 | 
			
		||||
		//   https://sourceforge.net/p/keepass/discussion/329220/thread/d50a79d6/
 | 
			
		||||
		//   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;
 | 
			
		||||
@@ -146,6 +160,118 @@ namespace KeePassLib.Utility
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		internal static void Initialize()
 | 
			
		||||
		{
 | 
			
		||||
			Terminate();
 | 
			
		||||
 | 
			
		||||
			// m_fOwnWindow = fOwnWindow;
 | 
			
		||||
 | 
			
		||||
			if(IsRequired(1530))
 | 
			
		||||
			{
 | 
			
		||||
				try
 | 
			
		||||
				{
 | 
			
		||||
					ThreadStart ts = new ThreadStart(MonoWorkarounds.FixClipThread);
 | 
			
		||||
					m_thFixClip = new Thread(ts);
 | 
			
		||||
					m_thFixClip.Start();
 | 
			
		||||
				}
 | 
			
		||||
				catch(Exception) { Debug.Assert(false); }
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		internal static void Terminate()
 | 
			
		||||
		{
 | 
			
		||||
			if(m_thFixClip != null)
 | 
			
		||||
			{
 | 
			
		||||
				try { m_thFixClip.Abort(); }
 | 
			
		||||
				catch(Exception) { Debug.Assert(false); }
 | 
			
		||||
 | 
			
		||||
				m_thFixClip = null;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static void FixClipThread()
 | 
			
		||||
		{
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
#if !KeePassUAP
 | 
			
		||||
				const string strXSel = "xsel";
 | 
			
		||||
				const AppRunFlags rfW = AppRunFlags.WaitForExit;
 | 
			
		||||
 | 
			
		||||
				string strLast = null;
 | 
			
		||||
				while(true)
 | 
			
		||||
				{
 | 
			
		||||
					string str = NativeLib.RunConsoleApp(strXSel,
 | 
			
		||||
						"--output --clipboard");
 | 
			
		||||
					if(str == null) return; // 'xsel' not installed
 | 
			
		||||
 | 
			
		||||
					if(str != strLast)
 | 
			
		||||
					{
 | 
			
		||||
						if(NeedClipboardWorkaround())
 | 
			
		||||
							NativeLib.RunConsoleApp(strXSel,
 | 
			
		||||
								"--input --clipboard", str, rfW);
 | 
			
		||||
 | 
			
		||||
						strLast = str;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					Thread.Sleep(250);
 | 
			
		||||
				}
 | 
			
		||||
#endif
 | 
			
		||||
			}
 | 
			
		||||
			catch(ThreadAbortException)
 | 
			
		||||
			{
 | 
			
		||||
				try { Thread.ResetAbort(); }
 | 
			
		||||
				catch(Exception) { Debug.Assert(false); }
 | 
			
		||||
			}
 | 
			
		||||
			catch(Exception) { Debug.Assert(false); }
 | 
			
		||||
			finally { m_thFixClip = null; }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static bool NeedClipboardWorkaround()
 | 
			
		||||
		{
 | 
			
		||||
			const bool bDef = true;
 | 
			
		||||
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
				string strHandle = (NativeLib.RunConsoleApp("xdotool",
 | 
			
		||||
					"getactivewindow") ?? string.Empty).Trim();
 | 
			
		||||
				if(strHandle.Length == 0) return bDef;
 | 
			
		||||
 | 
			
		||||
				// IntPtr h = new IntPtr(long.Parse(strHandle));
 | 
			
		||||
				long.Parse(strHandle); // Validate
 | 
			
		||||
 | 
			
		||||
				// Detection of own windows based on Form.Handle
 | 
			
		||||
				// comparisons doesn't work reliably (Mono's handles
 | 
			
		||||
				// are usually off by 1)
 | 
			
		||||
				// Predicate<IntPtr> fOwnWindow = m_fOwnWindow;
 | 
			
		||||
				// if(fOwnWindow != null)
 | 
			
		||||
				// {
 | 
			
		||||
				//	if(fOwnWindow(h)) return true;
 | 
			
		||||
				// }
 | 
			
		||||
				// else { Debug.Assert(false); }
 | 
			
		||||
 | 
			
		||||
				string strWmClass = (NativeLib.RunConsoleApp("xprop",
 | 
			
		||||
					"-id " + strHandle + " WM_CLASS") ?? string.Empty);
 | 
			
		||||
 | 
			
		||||
				if(strWmClass.IndexOf("\"" + PwDefs.ResClass + "\"",
 | 
			
		||||
					StrUtil.CaseIgnoreCmp) >= 0) return true;
 | 
			
		||||
 | 
			
		||||
				// Workaround for Remmina
 | 
			
		||||
				if(strWmClass.IndexOf("\"Remmina\"",
 | 
			
		||||
					StrUtil.CaseIgnoreCmp) >= 0) return true;
 | 
			
		||||
 | 
			
		||||
				return false;
 | 
			
		||||
			}
 | 
			
		||||
			catch(ThreadAbortException) { throw; }
 | 
			
		||||
			catch(Exception) { Debug.Assert(false); }
 | 
			
		||||
 | 
			
		||||
			return bDef;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
#if !KeePassUAP
 | 
			
		||||
		public static void ApplyTo(Form f)
 | 
			
		||||
		{
 | 
			
		||||
			if(!MonoWorkarounds.IsRequired()) return;
 | 
			
		||||
			if(f == null) { Debug.Assert(false); return; }
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Ensure that the file ~/.recently-used is valid (in order to
 | 
			
		||||
		/// prevent Mono's FileDialog from crashing).
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -669,7 +669,8 @@ namespace KeePassLib.Utility
 | 
			
		||||
			return DateTime.TryParse(str, out dt);
 | 
			
		||||
#else
 | 
			
		||||
			try { dt = DateTime.Parse(str); return true; }
 | 
			
		||||
			catch(Exception) { dt = DateTime.MinValue; return false; }
 | 
			
		||||
			catch(Exception) { dt = DateTime.UtcNow; }
 | 
			
		||||
			return false;
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -1722,5 +1723,16 @@ namespace KeePassLib.Utility
 | 
			
		||||
 | 
			
		||||
			return iCount;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		internal static string ReplaceNulls(string str)
 | 
			
		||||
		{
 | 
			
		||||
			if(str == null) { Debug.Assert(false); return null; }
 | 
			
		||||
 | 
			
		||||
			if(str.IndexOf('\0') < 0) return str;
 | 
			
		||||
 | 
			
		||||
			// Replacing null characters by spaces is the
 | 
			
		||||
			// behavior of Notepad (on Windows 10)
 | 
			
		||||
			return str.Replace('\0', ' ');
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -38,11 +38,18 @@ namespace KeePassLib.Utility
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public const int PwTimeLength = 7;
 | 
			
		||||
 | 
			
		||||
		public static readonly DateTime SafeMinValueUtc = new DateTime(
 | 
			
		||||
			DateTime.MinValue.Ticks + TimeSpan.TicksPerDay, DateTimeKind.Utc);
 | 
			
		||||
		public static readonly DateTime SafeMaxValueUtc = new DateTime(
 | 
			
		||||
			DateTime.MaxValue.Ticks - TimeSpan.TicksPerDay, DateTimeKind.Utc);
 | 
			
		||||
 | 
			
		||||
#if !KeePassLibSD
 | 
			
		||||
		private static string m_strDtfStd = null;
 | 
			
		||||
		private static string m_strDtfDate = null;
 | 
			
		||||
#endif
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		// private static long m_lTicks2PowLess1s = 0;
 | 
			
		||||
 | 
			
		||||
		private static DateTime? m_odtUnixRoot = null;
 | 
			
		||||
		public static DateTime UnixRoot
 | 
			
		||||
		{
 | 
			
		||||
@@ -50,8 +57,8 @@ namespace KeePassLib.Utility
 | 
			
		||||
			{
 | 
			
		||||
				if(m_odtUnixRoot.HasValue) return m_odtUnixRoot.Value;
 | 
			
		||||
		/// Pack a <c>DateTime</c> object into 5 bytes. Layout: 2 zero bits,
 | 
			
		||||
				DateTime dtRoot = (new DateTime(1970, 1, 1, 0, 0, 0, 0,
 | 
			
		||||
					DateTimeKind.Utc)).ToLocalTime();
 | 
			
		||||
				DateTime dtRoot = new DateTime(1970, 1, 1, 0, 0, 0, 0,
 | 
			
		||||
					DateTimeKind.Utc);
 | 
			
		||||
		/// year 12 bits, month 4 bits, day 5 bits, hour 5 bits, minute 6
 | 
			
		||||
				m_odtUnixRoot = dtRoot;
 | 
			
		||||
				return dtRoot;
 | 
			
		||||
@@ -63,10 +70,11 @@ namespace KeePassLib.Utility
 | 
			
		||||
		/// <returns></returns>
 | 
			
		||||
		/// bits, second 6 bits.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		/// <param name="dt"></param>
 | 
			
		||||
		/// <returns></returns>
 | 
			
		||||
		[Obsolete]
 | 
			
		||||
		public static byte[] PackTime(DateTime dt)
 | 
			
		||||
		{
 | 
			
		||||
			dt = ToLocal(dt, true);
 | 
			
		||||
 | 
			
		||||
			byte[] pb = new byte[5];
 | 
			
		||||
 | 
			
		||||
			// Pack time to 5 byte structure:
 | 
			
		||||
@@ -88,6 +96,7 @@ namespace KeePassLib.Utility
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		/// <param name="pb">Packed time, 5 bytes.</param>
 | 
			
		||||
		/// <returns>Unpacked <c>DateTime</c> object.</returns>
 | 
			
		||||
		[Obsolete]
 | 
			
		||||
		public static DateTime UnpackTime(byte[] pb)
 | 
			
		||||
		{
 | 
			
		||||
			Debug.Assert((pb != null) && (pb.Length == 5));
 | 
			
		||||
@@ -104,7 +113,8 @@ namespace KeePassLib.Utility
 | 
			
		||||
			int nMinute = ((n4 & 0x0000000F) << 2) | (n5 >> 6);
 | 
			
		||||
			int nSecond = n5 & 0x0000003F;
 | 
			
		||||
 | 
			
		||||
			return new DateTime(nYear, nMonth, nDay, nHour, nMinute, nSecond);
 | 
			
		||||
			return (new DateTime(nYear, nMonth, nDay, nHour, nMinute,
 | 
			
		||||
				nSecond, DateTimeKind.Local)).ToUniversalTime();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
@@ -112,10 +122,13 @@ namespace KeePassLib.Utility
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		/// <param name="dt">Object to be encoded.</param>
 | 
			
		||||
		/// <returns>Packed time, 7 bytes (<c>PW_TIME</c>).</returns>
 | 
			
		||||
		[Obsolete]
 | 
			
		||||
		public static byte[] PackPwTime(DateTime dt)
 | 
			
		||||
		{
 | 
			
		||||
			Debug.Assert(PwTimeLength == 7);
 | 
			
		||||
 | 
			
		||||
			dt = ToLocal(dt, true);
 | 
			
		||||
 | 
			
		||||
			byte[] pb = new byte[7];
 | 
			
		||||
			pb[0] = (byte)(dt.Year & 0xFF);
 | 
			
		||||
			pb[1] = (byte)(dt.Year >> 8);
 | 
			
		||||
@@ -133,6 +146,7 @@ namespace KeePassLib.Utility
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		/// <param name="pb">Packed time, 7 bytes.</param>
 | 
			
		||||
		/// <returns>Unpacked <c>DateTime</c> object.</returns>
 | 
			
		||||
		[Obsolete]
 | 
			
		||||
		public static DateTime UnpackPwTime(byte[] pb)
 | 
			
		||||
		{
 | 
			
		||||
			Debug.Assert(PwTimeLength == 7);
 | 
			
		||||
@@ -140,8 +154,8 @@ namespace KeePassLib.Utility
 | 
			
		||||
			Debug.Assert(pb != null); if(pb == null) throw new ArgumentNullException("pb");
 | 
			
		||||
			Debug.Assert(pb.Length == 7); if(pb.Length != 7) throw new ArgumentException();
 | 
			
		||||
 | 
			
		||||
			return new DateTime(((int)pb[1] << 8) | (int)pb[0], (int)pb[2], (int)pb[3],
 | 
			
		||||
				(int)pb[4], (int)pb[5], (int)pb[6]);
 | 
			
		||||
			return (new DateTime(((int)pb[1] << 8) | (int)pb[0], (int)pb[2], (int)pb[3],
 | 
			
		||||
				(int)pb[4], (int)pb[5], (int)pb[6], DateTimeKind.Local)).ToUniversalTime();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
@@ -151,23 +165,32 @@ namespace KeePassLib.Utility
 | 
			
		||||
		/// <returns>String representing the specified <c>DateTime</c> object.</returns>
 | 
			
		||||
		public static string ToDisplayString(DateTime dt)
 | 
			
		||||
		{
 | 
			
		||||
			return dt.ToString();
 | 
			
		||||
			return ToLocal(dt, true).ToString();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static string ToDisplayStringDateOnly(DateTime dt)
 | 
			
		||||
		{
 | 
			
		||||
			return dt.ToString("d");
 | 
			
		||||
			return ToLocal(dt, true).ToString("d");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static DateTime FromDisplayString(string strDisplay)
 | 
			
		||||
		{
 | 
			
		||||
			DateTime dt;
 | 
			
		||||
			if(FromDisplayStringEx(strDisplay, out dt)) return dt;
 | 
			
		||||
			return DateTime.Now;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static bool FromDisplayStringEx(string strDisplay, out DateTime dt)
 | 
			
		||||
		{
 | 
			
		||||
#if KeePassLibSD
 | 
			
		||||
			try { dt = DateTime.Parse(strDisplay); return dt; }
 | 
			
		||||
			try { dt = ToLocal(DateTime.Parse(strDisplay), true); return true; }
 | 
			
		||||
			catch(Exception) { }
 | 
			
		||||
#else
 | 
			
		||||
			if(DateTime.TryParse(strDisplay, out dt)) return dt;
 | 
			
		||||
			if(DateTime.TryParse(strDisplay, out dt))
 | 
			
		||||
			{
 | 
			
		||||
				dt = ToLocal(dt, true);
 | 
			
		||||
				return true;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// For some custom formats specified using the Control Panel,
 | 
			
		||||
			// DateTime.ToString returns the correct string, but
 | 
			
		||||
@@ -175,19 +198,25 @@ namespace KeePassLib.Utility
 | 
			
		||||
			// 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);
 | 
			
		||||
				DateTime dtUni = new DateTime(2111, 3, 4, 5, 6, 7, DateTimeKind.Local);
 | 
			
		||||
				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;
 | 
			
		||||
			{
 | 
			
		||||
				dt = ToLocal(dt, true);
 | 
			
		||||
				return true;
 | 
			
		||||
			}
 | 
			
		||||
			if(DateTime.TryParseExact(strDisplay, m_strDtfDate, null, dts, out dt))
 | 
			
		||||
				return dt;
 | 
			
		||||
			{
 | 
			
		||||
				dt = ToLocal(dt, true);
 | 
			
		||||
				return true;
 | 
			
		||||
			}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
			Debug.Assert(false);
 | 
			
		||||
			return DateTime.Now;
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
#if !KeePassLibSD
 | 
			
		||||
@@ -277,8 +306,10 @@ namespace KeePassLib.Utility
 | 
			
		||||
 | 
			
		||||
		public static string SerializeUtc(DateTime dt)
 | 
			
		||||
		{
 | 
			
		||||
			string str = dt.ToUniversalTime().ToString("s");
 | 
			
		||||
			if(str.EndsWith("Z") == false) str += "Z";
 | 
			
		||||
			Debug.Assert(dt.Kind != DateTimeKind.Unspecified);
 | 
			
		||||
 | 
			
		||||
			string str = ToUtc(dt, false).ToString("s");
 | 
			
		||||
			if(!str.EndsWith("Z")) str += "Z";
 | 
			
		||||
			return str;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -289,23 +320,13 @@ namespace KeePassLib.Utility
 | 
			
		||||
			if(str.EndsWith("Z")) str = str.Substring(0, str.Length - 1);
 | 
			
		||||
 | 
			
		||||
			bool bResult = StrUtil.TryParseDateTime(str, out dt);
 | 
			
		||||
			if(bResult) dt = dt.ToLocalTime();
 | 
			
		||||
			if(bResult) dt = ToUtc(dt, true);
 | 
			
		||||
			return bResult;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Deserializes a UTC XML DateTime to a local time, or returns defaultValue if it could not be parsed
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public static DateTime DeserializeUtcOrDefault(string xmlDateTimeString, DateTime defaultValue)
 | 
			
		||||
		public static double SerializeUnix(DateTime dt)
 | 
			
		||||
		{
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
				return System.Xml.XmlConvert.ToDateTime(xmlDateTimeString, System.Xml.XmlDateTimeSerializationMode.Local);
 | 
			
		||||
			}
 | 
			
		||||
			catch(FormatException)
 | 
			
		||||
			{
 | 
			
		||||
				return defaultValue;
 | 
			
		||||
			}
 | 
			
		||||
			return (ToUtc(dt, false) - TimeUtil.UnixRoot).TotalSeconds;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -322,15 +343,21 @@ namespace KeePassLib.Utility
 | 
			
		||||
			}
 | 
			
		||||
			catch(Exception) { Debug.Assert(false); }
 | 
			
		||||
 | 
			
		||||
			return DateTime.Now;
 | 
			
		||||
			return DateTime.UtcNow;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
#if !KeePassLibSD
 | 
			
		||||
		[Obsolete]
 | 
			
		||||
		public static DateTime? ParseUSTextDate(string strDate)
 | 
			
		||||
		{
 | 
			
		||||
			return ParseUSTextDate(strDate, DateTimeKind.Unspecified);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static string[] m_vUSMonths = null;
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Parse a US textual date string, like e.g. "January 02, 2012".
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public static DateTime? ParseUSTextDate(string strDate)
 | 
			
		||||
		public static DateTime? ParseUSTextDate(string strDate, DateTimeKind k)
 | 
			
		||||
		{
 | 
			
		||||
			if(strDate == null) { Debug.Assert(false); return null; }
 | 
			
		||||
 | 
			
		||||
@@ -352,7 +379,7 @@ namespace KeePassLib.Utility
 | 
			
		||||
					int iDay, iYear;
 | 
			
		||||
					if(int.TryParse(strDay, out iDay) &&
 | 
			
		||||
						int.TryParse(v[1].Trim(), out iYear))
 | 
			
		||||
						return new DateTime(iYear, i + 1, iDay);
 | 
			
		||||
						return new DateTime(iYear, i + 1, iDay, 0, 0, 0, k);
 | 
			
		||||
					else { Debug.Assert(false); return null; }
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
@@ -362,11 +389,13 @@ namespace KeePassLib.Utility
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		private static readonly DateTime m_dtInvMin =
 | 
			
		||||
			new DateTime(2999, 12, 27, 23, 59, 59);
 | 
			
		||||
			new DateTime(2999, 12, 27, 23, 59, 59, DateTimeKind.Utc);
 | 
			
		||||
		private static readonly DateTime m_dtInvMax =
 | 
			
		||||
			new DateTime(2999, 12, 29, 23, 59, 59);
 | 
			
		||||
			new DateTime(2999, 12, 29, 23, 59, 59, DateTimeKind.Utc);
 | 
			
		||||
		public static int Compare(DateTime dtA, DateTime dtB, bool bUnkIsPast)
 | 
			
		||||
		{
 | 
			
		||||
			Debug.Assert(dtA.Kind == dtB.Kind);
 | 
			
		||||
 | 
			
		||||
			if(bUnkIsPast)
 | 
			
		||||
			{
 | 
			
		||||
				// 2999-12-28 23:59:59 in KeePass 1.x means 'unknown';
 | 
			
		||||
@@ -399,5 +428,64 @@ namespace KeePassLib.Utility
 | 
			
		||||
			return Compare(tlA.LastModificationTime, tlB.LastModificationTime,
 | 
			
		||||
				bUnkIsPast);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static DateTime ToUtc(DateTime dt, bool bUnspecifiedIsUtc)
 | 
			
		||||
		{
 | 
			
		||||
			DateTimeKind k = dt.Kind;
 | 
			
		||||
			if(k == DateTimeKind.Utc) return dt;
 | 
			
		||||
			if(k == DateTimeKind.Local) return dt.ToUniversalTime();
 | 
			
		||||
 | 
			
		||||
			Debug.Assert(k == DateTimeKind.Unspecified);
 | 
			
		||||
			if(bUnspecifiedIsUtc)
 | 
			
		||||
				return new DateTime(dt.Ticks, DateTimeKind.Utc);
 | 
			
		||||
			return dt.ToUniversalTime(); // Unspecified = local
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		public static DateTime ToLocal(DateTime dt, bool bUnspecifiedIsLocal)
 | 
			
		||||
		{
 | 
			
		||||
			DateTimeKind k = dt.Kind;
 | 
			
		||||
			if(k == DateTimeKind.Local) return dt;
 | 
			
		||||
			if(k == DateTimeKind.Utc) return dt.ToLocalTime();
 | 
			
		||||
 | 
			
		||||
			Debug.Assert(k == DateTimeKind.Unspecified);
 | 
			
		||||
			if(bUnspecifiedIsLocal)
 | 
			
		||||
				return new DateTime(dt.Ticks, DateTimeKind.Local);
 | 
			
		||||
			return dt.ToLocalTime(); // Unspecified = UTC
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		/* internal static DateTime RoundToMultOf2PowLess1s(DateTime dt)
 | 
			
		||||
		{
 | 
			
		||||
			long l2Pow = m_lTicks2PowLess1s;
 | 
			
		||||
			if(l2Pow == 0)
 | 
			
		||||
			{
 | 
			
		||||
				l2Pow = 1;
 | 
			
		||||
				while(true)
 | 
			
		||||
				{
 | 
			
		||||
					l2Pow <<= 1;
 | 
			
		||||
					if(l2Pow >= TimeSpan.TicksPerSecond) break;
 | 
			
		||||
				}
 | 
			
		||||
				l2Pow >>= 1;
 | 
			
		||||
				m_lTicks2PowLess1s = l2Pow;
 | 
			
		||||
 | 
			
		||||
				Debug.Assert(TimeSpan.TicksPerSecond == 10000000L); // .NET
 | 
			
		||||
				Debug.Assert(l2Pow == (1L << 23)); // .NET
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			long l = dt.Ticks;
 | 
			
		||||
			if((l % l2Pow) == 0L) return dt;
 | 
			
		||||
 | 
			
		||||
			// Round down to full second
 | 
			
		||||
			l /= TimeSpan.TicksPerSecond;
 | 
			
		||||
			l *= TimeSpan.TicksPerSecond;
 | 
			
		||||
 | 
			
		||||
			// Round up to multiple of l2Pow
 | 
			
		||||
			long l2PowM1 = l2Pow - 1L;
 | 
			
		||||
			l = (l + l2PowM1) & ~l2PowM1;
 | 
			
		||||
			DateTime dtRnd = new DateTime(l, dt.Kind);
 | 
			
		||||
 | 
			
		||||
			Debug.Assert((dtRnd.Ticks % l2Pow) == 0L);
 | 
			
		||||
			Debug.Assert(dtRnd.ToString("u") == dt.ToString("u"));
 | 
			
		||||
			return dtRnd;
 | 
			
		||||
		} */
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
  KeePass Password Safe - The Open-Source Password Manager
 | 
			
		||||
  Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
 | 
			
		||||
  Copyright (C) 2003-2017 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
 | 
			
		||||
@@ -285,7 +285,7 @@ namespace KeePassLib.Utility
 | 
			
		||||
				else // Unhide
 | 
			
		||||
				{
 | 
			
		||||
					fa &= ~FileAttributes.Hidden;
 | 
			
		||||
					if((long)fa == 0) fa |= FileAttributes.Normal;
 | 
			
		||||
					if((long)fa == 0) fa = FileAttributes.Normal;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				File.SetAttributes(strFile, fa);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user